不用分析页面,无脑抓取table数据

不用分析页面,无脑抓取table数据

如果你的爬虫所要爬取的内容存在于页面的table标签中,那么本文所探索的方法,对你非常有帮助。

下面两个网址中,都有非常规范的table数据

北京有哪些500强企业?2019北京500强企业名单_排行榜123网www.phb123.com图标中国企业500强_百度百科baike.baidu.com图标

前者是北京500强企业名单,后者是中国企业500强名单

常规的抓取,你需要分析页面,准确的找到这部分内容的标签位置,然后进行定点抓取,我在分析了几个页面后发现,这些表格的数据都很相似

  1. 他们存储于table标签中
  2. 第一个tr 都是第一行的标题
  3. 从第二个tr开始都是数据内容
<table border="0" cellpadding="0" cellspacing="0" style="width: 100%" width="789">
	<colgroup>
		<col />
		<col />
		<col />
	</colgroup>
	<tbody>
		<tr height="18">
			<td height="18" style="height:18px;width:72px;">
				排名</td>
			<td style="width:533px;">
				公司名称(中英文)</td>
			<td style="width:184px;">
				营业收入(百万美元)</td>
		</tr>
		<tr height="18">
			<td height="18" style="height:18px;">
				2</td>
			<td>
				国家电网公司(STATE GRID)</td>
			<td>
				348903.1</td>
		</tr>
		<tr height="18">
			<td height="18" style="height:18px;">
				3</td>
			<td>
				中国石油化工集团公司(SINOPEC GROUP)</td>
			<td>
				326953</td>
		</tr>
		<tr height="18">
			<td height="18" style="height:18px;">
				4</td>
			<td>
				中国石油天然气集团公司(CHINA NATIONAL PETROLEUM)</td>
			<td>
				326007.6</td>
		</tr>

既然他们长的都一样,为何不写一个通用的表格抓取函数内,这样,再遇到这类页面时,就可以快速抓取了,之所以不是写一个通用的表格抓取爬虫,是因为不同的页面获取方式不一样,但只要拿到了html,那么剩下的分析提取过程都是一样的。

想要一个函数应对所有的情况,就需要对table特别了解,这样,这个函数才能cover住大多数情况,至于少数特别的页面,不在这个函数的处理范围内。

第一个tr是标题行,其内部的标签可以是th,也可以是td, 对于tbody中的tr,其内部都是td,这一点要在写程序的时候注意。在获取td内容时,我只关心实际的文字内容,至于加粗标签或者链接都不是我想要的,因此,需要在代码里只提取td下的文字内容。

思路定下来了,代码也就好写了

import pprint
import requests
from lxml import etree


def get_table_from_html(html):
    tree = etree.HTML(html)
    # 寻找所有的table标签
    table_lst = tree.xpath("//table")
    table_data_lst = []
    for table in table_lst:
        table_data_lst.append(get_table(table))

    return table_data_lst


def get_table(table_ele):
    """
    获取table数据
    :param table_ele:
    :return:
    """
    tr_lst = table_ele.xpath(".//tr")
    # 第一行通常来说都是标题
    title_data = get_title(tr_lst[0])
    # 第一行后面都是数据
    data = get_data(tr_lst[1:])

    return {
        'title': title_data,
        'data': data
    }


def get_title(tr_ele):
    """
    获取标题
    标题可能用th 标签,也可能用td标签
    :param tr_ele:
    :return:
    """
    # 先寻找th标签
    title_lst = get_tr_data_by_tag(tr_ele, 'th')
    if not title_lst:
        title_lst = get_tr_data_by_tag(tr_ele, 'td')

    return title_lst


def get_data(tr_lst):
    """
    获取数据
    :param tr_lst:
    :return:
    """
    datas = []
    for tr in tr_lst:
        tr_data = get_tr_data_by_tag(tr, 'td')
        datas.append(tr_data)

    return datas


def get_tr_data_by_tag(tr, tag):
    """
    获取一行数据
    :param tr:
    :param tag:
    :return:
    """
    datas = []
    nodes = tr.xpath(".//{tag}".format(tag=tag))
    for node in nodes:
        text = node.xpath('string(.)').strip()
        datas.append(text)

    return datas


def get_html(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
    }
    res = requests.get(url, headers=headers)
    res.encoding = 'utf-8'
    return res.text


def run():
    url = 'https://baike.baidu.com/item/%E4%B8%AD%E5%9B%BD%E4%BC%81%E4%B8%9A500%E5%BC%BA/5542706?fr=aladdin'
    # url = "https://www.phb123.com/qiye/35109.html"
    html = get_html(url)
    table_lst = get_table_from_html(html)
    pprint.pprint(table_lst)


if __name__ == '__main__':
    run()

目前,只是使用了几个网页进行了测试,如果你遇到了该方法无法准确抓取的页面,可以留言给我,我会根据页面内容改进这个表格抓取方法

编辑于 2019-10-18
python爬虫
 
 
res=etree.HTML(res.text)
get_table(res)
posted @ 2020-06-24 11:15  逐梦~前行  阅读(408)  评论(0编辑  收藏  举报