diff --git a/markdownify/__init__.py b/markdownify/__init__.py
index cab4f36..86226d2 100644
--- a/markdownify/__init__.py
+++ b/markdownify/__init__.py
@@ -376,10 +376,16 @@ class MarkdownConverter(object):
         return '\n\n' + text + '\n\n'
 
     def convert_td(self, el, text, convert_as_inline):
-        return ' ' + text.strip().replace("\n", " ") + ' |'
+        colspan = 1
+        if 'colspan' in el.attrs:
+            colspan = int(el['colspan'])
+        return ' ' + text.strip().replace("\n", " ") + ' |' * colspan
 
     def convert_th(self, el, text, convert_as_inline):
-        return ' ' + text + ' |'
+        colspan = 1
+        if 'colspan' in el.attrs:
+            colspan = int(el['colspan'])
+        return ' ' + text.strip().replace("\n", " ") + ' |' * colspan
 
     def convert_tr(self, el, text, convert_as_inline):
         cells = el.find_all(['td', 'th'])
@@ -392,7 +398,13 @@ class MarkdownConverter(object):
         underline = ''
         if is_headrow and not el.previous_sibling:
             # first row and is headline: print headline underline
-            underline += '| ' + ' | '.join(['---'] * len(cells)) + ' |' + '\n'
+            full_colspan = 0
+            for cell in cells:
+                if "colspan" in cell.attrs:
+                    full_colspan += int(cell["colspan"])
+                else:
+                    full_colspan += 1
+            underline += '| ' + ' | '.join(['---'] * full_colspan) + ' |' + '\n'
         elif (not el.previous_sibling
               and (el.parent.name == 'table'
                    or (el.parent.name == 'tbody'

diff --git a/tests/test_tables.py b/tests/test_tables.py
index 42f3a25..9120c29 100644
--- a/tests/test_tables.py
+++ b/tests/test_tables.py
@@ -209,6 +209,23 @@ table_with_caption = """TEXT<table><caption>Caption</caption>
     </tbody>
 </table>"""
 
+table_with_colspan = """<table>
+    <tr>
+        <th colspan="2">Name</th>
+        <th>Age</th>
+    </tr>
+    <tr>
+        <td>Jill</td>
+        <td>Smith</td>
+        <td>50</td>
+    </tr>
+    <tr>
+        <td>Eve</td>
+        <td>Jackson</td>
+        <td>94</td>
+    </tr>
+</table>"""
+
 
 def test_table():
     assert md(table) == '\n\n| Firstname | Lastname | Age |\n| --- | --- | --- |\n| Jill | Smith | 50 |\n| Eve | Jackson | 94 |\n\n'
@@ -222,3 +239,4 @@ def test_table():
     assert md(table_missing_head) == '\n\n| Firstname | Lastname | Age |\n| --- | --- | --- |\n| Jill | Smith | 50 |\n| Eve | Jackson | 94 |\n\n'
     assert md(table_body) == '\n\n| Firstname | Lastname | Age |\n| --- | --- | --- |\n| Jill | Smith | 50 |\n| Eve | Jackson | 94 |\n\n'
     assert md(table_with_caption) == 'TEXT\n\nCaption\n| Firstname | Lastname | Age |\n| --- | --- | --- |\n\n'
+    assert md(table_with_colspan) == '\n\n| Name | | Age |\n| --- | --- | --- |\n| Jill | Smith | 50 |\n| Eve | Jackson | 94 |\n\n'

Table merge cell horizontally
### Summary
`colspan` attribute ignored in conversion, causing problems.

### Description
In HTML, the `colspan` attribute of `<td>` and `<th>` extends the cell to span multiple columns.

Currently, all cells are handled the same, causing inconsistent numbers of columns on each row of the table.
tests/test_tables.py::test_table