爬取网页中表格类信息数据并存储到excel表中
需要的工具:
- Python3
- requests
- BeautifulSoup
- openpyxl
- re
- PIL
- urllib
- pytesseract
本文两个例子的完整代码:https://github.com/huanyouchen/python-spider
本文目标
爬取网页中表格类的信息,并将这些信息存储到excel中。
实例1
目标URL: http://permit.mep.gov.cn/permitExt/outside/Publicity
该网站展示的是全国排污许可证管理信息平台-公开端中许可信息公开的相关信息,目标是获取所有公开页面的表格中的省/直辖市、地市、许可证编号、单位名称、行业类别、有效期限、发证日期、查看链接,并将所有信息写入excel中。
实例2
目标URL: http://info.425500.cn/category-1-0-0-0-p1.html
该网站展示的是江华地区物品交易平台的交易信息,目标是获取每单交易的标题,发布时间,浏览次数,所在区域,联系电话,和交易详细链接,并将所有信息写入excel中。
爬取结果
实例1的结果
实例2的结果
过程分析
完整代码在本文开头已经给出地址,需要自取。下面分析部分内容。
实例1分析
在get_end_page_num()函数中,获取最后一页的页码,需要用正则表达式来提取出第一个数字,也就是2019,表示一共有2019个页面。
1 | # 获取最后一页页码 |
获取表格数据核心代码:
1 | trs = soup.find('div', class_='tb-con').find_all('tr')[1:] |
在表格中,tr代表一行,td代表一列,外层循环获取每一行,内层循环获取每一行的每一列。
row_data存储一行中各列的数据,也就是省/直辖市、地市、许可证编号等,但是最后一列是超链接,需要单独处理一下然后存入到row_data中。
page_data存储的是每页的表格数据,也就是把这一页中的所有行数据row_data存到一起。
最后的data存储所有页page_data的数据。
本文使用openpyxl操作excel。将数据存入excel中:
1 | for i in range(2, len(data) + 2): |
存入excel表格中也需要用两个循环,i表示行递增,j表示每一行的列,将data中的数据依次存入即可。
其中有一个小知识点,爬到的查看链接是URL,需要用把url用超链接的形式写入Excel中,具体用法是在value里面加入=HYPERLINK
:
1 | sheet.cell(row=i, column=9, value=('=HYPERLINK("%s")' % (data[i-2][7]))) |
实例2分析
实例2比实例1复杂一点,主要有两点。
第一点,获取电话号码,该网站的电话号码不是文本形式,而是一个图片,用Chrome开发者工具查看相关源码如下:
1 | <li>联系方式:<span class="cBlack"> |
电话图片的地址为: http://info.425500.cn/public/ajax.aspx?action=drawinfoimage&in=8SwlFtKb9u10iAntlNhdM8Vg==&size=16
思路是提取出电话图片的地址url,然后用urllib中的urlretrieve
把图片下载到本地,然后使用Tesseract识别图片中的文字,将识别出来的结果返回得到文本形式的电话号码,然后写入excel中。
关于Tesseract的下载和使用: http://huanyouchen.github.io/2018/05/10/install-Tesseract-and-use-it-with-py/
这部分的实现代码:
1 | def img_to_str(image_path): |
另一个点是对浏览次数的获取。浏览次数相关页面源码如下:
1 | <span class="left news-span2">浏览 |
浏览次数使用后台脚本计算后返回给前端页面中的,先用Dev工具中的Network找到这段脚本:
该脚本地址为:http://info.425500.cn/public/ajax.aspx?action=addnum&id=6576&t=1
其中id为该次交易信息的id号,这个id号在本物品交易详情的url中,比如这个哈士奇出售的交易详情url: http://info.425500.cn/info-6576.html
思路是首先从物品交易详情页面的url中提取出该物品交易id号,将这个id号作为参数传入后台累加浏览次数脚本的url中,用request请求该脚本链接,然后用正则表达式提取出返回信息中的浏览次数。
这部分实现代码:
1 | info_id = re.findall('\d+', link.split('/')[-1])[0] # 通过网址获取交易编号 |