Python 爬虫小练习:基于 XPath 的表格信息爬取
创始人
2024-03-20 16:02:18

文章目录

    • 确定目标和分析思路
      • 目标
      • 思路
    • 观察情况
    • 爬取名单表
    • 爬取详情页二级信息
    • 爬虫请遵守相关法律法规,不要做违法犯罪的事情
    • 爬虫小技巧总结

这是一个 Python 爬虫的入门练习,我们通过 Request 请求数据,并通过 XPath 去匹配表格中的元素或者内容,使用 Pandas 进行数据的整理。下面我们 Step by Step 来完成这件事情。

确定目标和分析思路

目标

目标是从某个网站中爬取表格数据。我选择的网站是:http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaList (下不妨称为名单页)。

  • 这里有一个名单库,名单库里面有一些个人信息,包括姓名、单位名称等等。
  • 名单分页,需要不断点下一页加载更多信息。
  • 更多的信息需要点击名单上的姓名进入子页(下称为详情页)进行查看。需要循环点击,二级爬取。

思路

思路是我们通过名单页上的 XPath 选择和翻页,获得所有对应着每个人的详情页链接。之后遍历详情页链接,爬取信息,存为 csv 文件。

观察情况

按 F12 可以打开浏览器的开发者工具,选中 Network 页。

刷新名单页,可以看到信息流,包括 Request URL 和 Request Headers 等等。因为是密码登录的,我们在发送请求时需要 Cookie 作为头信息。

点开第二页名单页,我们发现翻页只需要修改 url 链接 page= 后面的内容:http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaList?pinqing_dwdm=80002&is_yw=False&page=xxx

清空 Network 信息流,随意点一个名字,打开改名字对应的详情页。观察到,它的 Request URL 是:http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaEdit?zhuanjia_id=xxxxx。它以 get 的方式请求信息,且 zhuanjia_id 对应着每个人的 ID,只要改变这个 ID,就会返回不同人的信息。容易看到,ID 的信息,可以在名单页的姓名栏的 href 中找到。

尝试了,通过 pandas 的 pandas.read_html 读取网上的表格和基本的数据格式化操作在此处比较麻烦,故而,直接使用 XPath 定位。

爬取名单表

按照上述的思路,我们分两步走,先使用名单页,通过翻页汇总所有人对应的详情页信息。可以观察到的是

写好 Headers,通过 requests.get 返回网页信息,再利用 Xpath 进行提取之后存档。

代码如下:

import requests
from lxml import etree
import pandas as pd
# parameter = {
#             "key1":"value1",
#             "key2":"value2"
#             }
headers = {"Cache-Control": "max-age=0","Connection":"keep-alive","Cookie":"xxxxxxxxxx","Referer":"http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaList?pinqing_dwdm=80002&is_yw=False&page=2","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"}
total_page = 2111
dfs = pd.DataFrame(columns=['name','id']);
ind = 0
for i in range(2111,total_page+1):response = requests.get("http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaList? \pinqing_dwdm=80002&is_yw=False&page="+str(i), \headers = headers)#,params = parameter)# print(response.url)# print(response.text)# print(response.content)# print(response.encoding)# print(response.status_code)html=response.texttree=etree.HTML(html)NAME = tree.xpath('//*[@id="main-content"]/div/div/div/div/div[2]/div/table/tbody/tr/td[1]/a')IDHREF = tree.xpath('//*[@id="main-content"]/div/div/div/div/div[2]/div/table/tbody/tr/td[1]/a/@href')for j in range(0,len(NAME)):ind = ind+1print(ind)ids = str(IDHREF[j]).split('=')new = pd.DataFrame({'name':NAME[j].text, 'id':int(ids[1])},index=[ind])dfs=dfs.append(new) 
dfs.to_csv("./教授名字和ID.csv", encoding="utf_8_sig")

这里没有特别需要强调的地方,只不过这份代码不是写得非常高性能,有很多可以优化的地方,比如只要一个 tree.xpath。

爬取详情页二级信息

假设已经得到了爬取详情页需要 ID,这时候,我们可以通过不断地对微小区别的 url 们发送请求,就可以得到所以详情页信息。再通过开发者工具右键 XPath 拷贝工具,得到 XPath 匹配模式,粘贴提取信息,通过 Pandas 整理,存档。所用的代码如下:

import requests
from lxml import etree
import pandas as pd
ID1 = pd.read_csv('./教授名字和ID0.csv')
ID2 = pd.read_csv('./教授名字和ID.csv')
ID1n = list(map(int, ID1['id'])) 
ID2n = list(map(int, ID2['id'])) 
IDs = ID1n+ID2n
IDs.sort()header = {"Connection": "keep-alive",
"Cookie": "xxxx",
"Host": "py.ucas.ac.cn",
"Referer": "http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaList?pinqing_dwdm=80002&is_yw=False&page=1936",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
}
bg = 20617;
ed = len(IDs)
#ed = 2
data = pd.DataFrame(columns=['姓名','性别','单位','通讯地址','邮编','邮箱','手机',\'固话','出生日期','身份证号','学科专业','方向','导师类别',\'专业技术职务','银行户头','银行地址','银行号码'])
count = -1
for i in range(bg,ed):count = count+1id = IDs[i]print(str(IDs[bg])+"TO"+str(IDs[ed-1])+":"+str(i)+":"+str(id)+"进行中...")response = requests.get("http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaEdit?zhuanjia_id="+str(id),headers=header)html=response.text# print(html)# with open('test.html','w',encoding='utf-8') as f:#     f.write(html)tree=etree.HTML(html)zjxm = str(tree.xpath('//*[@id="ZJXM"]/@value')[0]) #姓名zjxb = str(tree.xpath('//*[@id="ZJXB"]/option[@selected="selected"]/@value')[0])#性别jsdw = str(tree.xpath('//*[@id="DWDM"]/option[@selected="selected"]')[0].text)#单位zjtxdz = str(tree.xpath('//*[@id="ZJTXDZ"]/@value')[0])#通讯地址zjyzbm = str(tree.xpath('//*[@id="ZJYZBM"]/@value')[0])#邮编UserName = str(tree.xpath('//*[@id="UserName"]/@value')[0])#邮箱zjsj = str(tree.xpath('//*[@id="ZJSJ"]/@value')[0])#手机zjtel = str(tree.xpath('//*[@id="ZJTEL"]/@value')[0])#固话zjcsrq = str(tree.xpath('//*[@id="ZJCSRQ"]/@value')[0])#出生日期zjhm = str(tree.xpath('//*[@id="zjhm"]/@value')[0])#身份证号tmp = tree.xpath('//*[@id="ZJ_XKZY"]/option[@selected="selected"]')if len(tmp)==0:zjxkzy = ''else:zjxkzy = str(tmp[0].text)#学科专业yjfx = str(tree.xpath('//*[@id="yjfx"]/@value')[0])#方向  zjlb = str(tree.xpath('//*[@id="ZJLB"]/option[@selected="selected"]')[0].text)#导师类别tmp = tree.xpath('//*[@id="ZJZWCODE"]/option[@selected="selected"]')if len(tmp)==0:zjzwcode = ''else:zjzwcode = str(tmp[0].text)#专业技术职务  bank_hutou = str(tree.xpath('//*[@id="bank_hutou"]/@value')[0])#银行户头bank_dizhi = str(tree.xpath('//*[@id="bank_dizhi"]/@value')[0])#银行地址bank_xingming = str(tree.xpath('//*[@id="bank_xingming"]/@value')[0])#银行号码data.loc[count] = [zjxm,zjxb,jsdw,zjtxdz,zjyzbm,UserName,zjsj,zjtel,zjcsrq,zjhm,zjxkzy,yjfx,zjlb,zjzwcode,bank_hutou,bank_dizhi,bank_xingming]
data.to_csv("./"+str(bg)+"_"+str(IDs[bg])+"TO"+str(i)+"_"+str(IDs[i])+"高校教授联系方式.csv", encoding="utf_8_sig")

我们知道,长时间的爬取,总会出现一些问题,比如网络拒绝问题。在我的代码中个,没有任何的 try 方式的异常捕捉。我采用的异常处理方式时,代码跑断了,先把中间结果手动地存下来。再手动地从断点出手动地开启代码重跑。
我享受这种手动挡的过程,而不需要任何的异常处理机制。

爬虫请遵守相关法律法规,不要做违法犯罪的事情

爬虫写得好,牢饭吃到饱。不爬私有数据,不把网站搞崩。不要将爬虫方法用于任何的盈利。

爬虫小技巧总结

  1. Request 的 Headers 信息可以通过直接从浏览器开发者工具信息流里面拷贝修改得到。

  2. 匹配信息的时候建议存一份 Python 请求返回的网页进行分析,而不是在浏览器中直接访问请求地址,根据返回的结果做元素匹配。因为有时候 Python 请求的得到的结果和浏览器请求得到的结果是不一样的。存 Python 返回的网页结果的代码示例如下:

    response = requests.get("http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaEdit?zhuanjia_id="+str(id),headers=header)
    html=response.text
    print(html)
    with open('test.html','w',encoding='utf-8') as f:f.write(html)
    
  3. 可以通过鼠标右键,检查元素,Copy XPath 得到 XPath 的匹配模式,黏贴到代码中接口。但寻找的结果为空或者不对的时候,可以对你要找的元素的姊妹单元复制 XPath,进行比对分析。

  4. 擅 XPath @ 功能。当我们要去 XPath 要取标签里面的元素的值的时候,可以用 @ 进行取值,如:tree.xpath('//*[@id="DWDM"]/option[@selected="selected"]')[0].text 此中中括号本表示索引,option[@selected="selected"] 表示在所有的 option 里面选择满足条件的(这里是下拉框产生的)。再比如 tree.xpath('//*[@id="ZJXM"]/@value')[0] 中 /@value 表示在所有 //*[@id="ZJXM"] 中取 value 的值,组成 list。

  5. 整理一份 Request+XPath 的模板如下,每次想要爬东西,复制修改即可用:

    import requests
    from lxml import etree
    import pandas as pd
    # parameter = {
    #             "key1":"value1",
    #             "key2":"value2"
    #             }
    header = {"Connection": "keep-alive",
    "Cookie": "xxx",
    "Host": "py.ucas.ac.cn",
    "Referer": "http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaList?pinqing_dwdm=80002&is_yw=False&page=1936",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
    }
    data = pd.DataFrame(columns=['姓名','单位'])
    response = requests.get("http://py.ucas.ac.cn/zh-cn/zhuanjia/ZhuanjiaEdit?zhuanjia_id=xxx",headers=header)#,params = parameter)
    html=response.text
    print(html)
    # print(response.url)
    # print(response.text)
    # print(response.content)
    # print(response.encoding)
    # print(response.status_code)
    with open('test.html','w',encoding='utf-8') as f:f.write(html)
    tree=etree.HTML(html)
    zjxm = str(tree.xpath('//*[@id="ZJXM"]/@value')[0]) #姓名
    jsdw = str(tree.xpath('//*[@id="DWDM"]/option[@selected="selected"]')[0].text)#单位
    data.loc[0] = [zjxm,jsdw]
    data.to_csv("xxx.csv", encoding="utf_8_sig")
    

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...