• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

25行代码爬取企查查超大表格,并保存到本地

互联网 diligentman 4周前 (01-31) 10次浏览

这里是个人吐槽,可略过

不知道大家写爬虫的时候有没有遇到过这种情况,看到那种表格形式的数据,就很头疼,因为我们要一个一个地去解析他们。
在解析网页数据地时候,我本人比较喜欢用xpath,拿企查查为例,下面是我是小白的时候写的代码(太菜了)…

25行代码爬取企查查超大表格,并保存到本地

def get_the_information(company_url):
    company_url = company_url
    # print(company_url)
    r = requests.get(company_url, headers=headers)
    # print(r.text)
    html = etree.HTML(r.text)
    First_list = []
    try:
        company_name = html.xpath('//h1/text()')[0]
    except Exception as e:
        company_name = ''

    # print(company_name)
    try:
        phone = html.xpath('//span[@class="cvlu"]/span[2]/text()')[0]
    except Exception:
        phone = '无'
    # print(phone)
    try:
        date = html.xpath('//table[@class="ntable"]//tr[1]/td[@class=""][2]/text()')[0].replace('n', '').replace(' ',
                                                                                                                  '')
    except Exception:
        date = ''
    # print(date)
    try:
        status = html.xpath('//table[@class="ntable"]//tr[1]/td[@class=""][1]/text()')[0].replace('n', '').replace(' ',
                                                                                                                    '')
    except Exception as e:
        status = '无'

    # print(status)

    try:
        address = html.xpath('//table[@class="ntable"]//tr[8]/td/span/a/text()')[0].replace('n', '').replace(' ', '')
    except Exception:
        address = '无'
    try:
        Subscribed_capital = int(
            html.xpath('//section[@id="Cominfo"]//table[@class="ntable"]//tr[2]/td[2]/text()')[0].replace('n',
                                                                                                          '').replace(
                ' ', '').split('万')[0]) / 10000
        # print(Subscribed_capital)
        Paid_capital = int(
            html.xpath('//section[@id="Cominfo"]//table[@class="ntable"]//tr[2]/td[4]/text()')[0].replace('n',
                                                                                                          '').replace(
                ' ', '').split('万')[0]) / 10000
        # print(Paid_capital)
    except Exception:
        pass
    try:
        Legal_representative = re.findall('<a href=".*?" class="bname"><h2 class="seo font-20">(.*?)</h2></a>', r.text)[
            0]
    except Exception:
        Legal_representative = '无'
    print(Legal_representative)
    # print(Legal_representative)
    unMain_HTML = html.xpath('//div[@id="employeeslist"]/table[@class="ntable ntable-odd"]//tr')
    # print(unMain_HTML)
    First_list.append(company_name)
    First_list.append(phone)
    First_list.append(date)
    First_list.append(status)
    First_list.append(address)
    First_list.append(Subscribed_capital)
    First_list.append(Paid_capital)
    First_list.append(Legal_representative)
    unMain_information = []
    for html in unMain_HTML:
        two_information = []
        try:
            name = html.xpath('td[2]//span[@class="seo font-14"]/text()')[0]
            position = html.xpath('td[@class="text-center"]/text()')[0].replace('n', '').replace(' ', '')
            two_information.append(name)
            two_information.append(position)
            unMain_information.append(two_information)
            # print(two_information)
        except Exception:
            pass
    # print(unMain_information)
    Main_HTML = html.xpath('//div[@id="ChangelistTable"]//table[@class="ntable"]//tr')
    Main_information = []
    for html in Main_HTML:
        One_informatin = []
        Change_data = html.xpath('./td[2]/text()')[0]
        Change_information = html.xpath('./td[3]/text()')[0].replace('n', '').replace(' ', '')
        try:
            Change_before = html.xpath('./td[4]//a/text()')[0].replace('n', '').replace(' ', '')
        except Exception:
            Change_before = ' '
        try:
            Change_after = html.xpath('./td[5]//a/text()')[0].replace('n', '').replace(' ', '')
        except Exception:
            Change_after = ' '
        One_informatin.append(Change_data)
        One_informatin.append(Change_information)
        One_informatin.append(Change_before)
        One_informatin.append(Change_after)
        Main_information.append(One_informatin)
    # for m in Main_information:
    #     print(m)
    # print(First_list)
    # print(unMain_information)
    return First_list, unMain_information, Main_information

现在回头看我写的代码,简直不忍直视,这么一大坨,就为了解析一个表格(我淦)。

随着技术的沉淀,现在学到了很多有用的库,通过引用这些库,我的代码可以做到25行搞定这种网页表格(连带保存),下面就给大家分享一下我的方法!

第一步——导入用到的库

import requests
from lxml import etree
import pandas as pd
import numpy as np

第二步——请求数据

headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",}
url = 'https://www.qcc.com/firm/8c9f7ddc1a7bcee3d1f7676773fe9404.html'
s = requests.Session()
r = s.get(url, headers=headers)

第三步(关键)——找到<table标签

至于为什么找<table 标签,我解释一下,是因为我们需要使用到pandas库中的 read_html方法,它可以自动把网页源码代码种,table标签中的表格数据,转换成列表。
table标签的样式:

<table border="1">
  <tr>
    <th></th>
    <th></th>
  </tr>
  <tr>
    <td></td>
    <td></td>
  </tr>
</table>

拿企查查为例,我们在网页源代码种找到table标签的位置
25行代码爬取企查查超大表格,并保存到本地
下面我们要做的就是把table标签的源代码给爬下来

html = etree.HTML(r.text)
table = html.xpath('//section[@id="Cominfo"]/table[@class="ntable"]')[0]
div_str = etree.tostring(table)

第四步——使用read_html()

我们只需要把div_str 放到read_html()的第一个参数的位置,后面接上编码,让header=1(作用是让第一行数据当表头,否则会多出来一行数字),因为返回的是个列表,我们接收第一个即可

df = pd.read_html(div_str, encoding='utf8', header=1)[0]
print(df)

结果如下:
25行代码爬取企查查超大表格,并保存到本地
我们把它的值遍历一下看看是什么

for i in df.values:
    print(i)

25行代码爬取企查查超大表格,并保存到本地
原来是这样的,跟网页中的表格格式基本一致,但是这并不是我们想要的形式,我们需要的是一个字典,是键值对。
此时我们就需要把这些表格处理一下了。

第五步——处理数据

这里可以观察到,每个列表的键和值都是紧挨的,而且第一个是键,第二个是值,有的列表会有很多重复值。并且列表的最后会有个‘nan’,我们需要把他去掉。

for i in df.values:
    l = list(i[:-1])
    l2 = list(set(l))
    l2.sort(key=l.index)
    print(l2)

此时的输出结果是这样的:
25行代码爬取企查查超大表格,并保存到本地
离成功又近了一步!

加下来要做的就是把表格中的数据,转换成键值对的形式,以便于我们存储为csv

这里我是用的是numpy中的列表分割,我把每个列表的元素以2为单位进行分割,得到若干小列表,然后字典的键就是列表的第一个值,字典的值就是列表的第二个值!

dict = {}
for i in df.values:
    l = list(i[:-1])
    l2 = list(set(l))
    l2.sort(key=l.index)
    arry_list = np.array_split(l2, len(l2) / 2)
    for L in arry_list:
        L = list(L)
        dict[L[0]] = L[1]
print(dict)

输出结果如下:
25行代码爬取企查查超大表格,并保存到本地

第六步——保存成表格

在得到字典后,我们要做的就是把它转换成dataframe,再使用pd.to_csv(),保存到本地
具体操作如下:

data = pd.DataFrame(dict, index=['阿里巴巴'])
print(data)
data.to_csv('阿里.csv')

第七步——查收数据

25行代码爬取企查查超大表格,并保存到本地
整体代码如下:

import requests
from lxml import etree
import pandas as pd
import numpy as np
headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",}
url = 'https://www.qcc.com/firm/8c9f7ddc1a7bcee3d1f7676773fe9404.html'
s = requests.Session()
r = s.get(url, headers=headers)
html = etree.HTML(r.text)
table = html.xpath('//section[@id="Cominfo"]/table[@class="ntable"]')[0]
div_str = etree.tostring(table)
df = pd.read_html(div_str, encoding='utf8', header=1)[0]
dict = {}
for i in df.values:
    l = list(i[:-1])
    l2 = list(set(l))
    l2.sort(key=l.index)
    arry_list = np.array_split(l2, len(l2) / 2)
    for L in arry_list:
        L = list(L)
        dict[L[0]] = L[1]
print(dict)
data = pd.DataFrame(dict, index=['阿里巴巴'])
print(data)
data.to_csv('阿里.csv')

注意事项:我们使用pandas和numpy得到的表格,需要使用list()强转一下,否则不能直接操作!

学到的话给博主点个关注哦~


程序员灯塔
转载请注明原文链接:25行代码爬取企查查超大表格,并保存到本地
喜欢 (0)