爬虫有风险,学习需谨慎。切记
本次介绍一个简单的案例,通过这个案例的分享基本上可以解决大部分html页面的抓取。
首先呢,在进行爬虫之前,需要先判断网页上面需要采集的数据是如何来的,有的网页是一个静态的html,有的则是通过xhr请求获取后端的数据,使用js在页面进行修改。一般来说如果是静态网页这种是比较好抓取的(例如政府网站,jsp),需要注意的问题是在于这个网站会不会对你的ip进行封锁,或者是在一段时间内你这个ip请求的数据是一样的。
如果是静态网页的话,需要使用xpath,进行网页上面的节点抓取。在python中需要使用库有 requests,lxml。因为是简单的案例,所以不需要其他的库了(例如正则库re,json,)
先确定网页的地址进行请求
response = requests.get(url=url, headers=headers)
这里发送的是一个get请求,地址上面通常会携带一些变量信息,这个url在复制的过程中可能会变成url编码,里面的中文是看不到的,可以找个地址解析工具,看到里面的内容。header就是伪造请求头,服务器可能会通过请求判断你的访问请求不是有浏览器发送的,而是通过爬虫脚本发出的。那么如何获取请求头呢,使用googl浏览器,按F12,打开开发者工具,随便找到一个请求,点开它,如图
在请求表头的下面就是对应的信息,例如cookie,user-agent。可以右击复制请求表头,这个也是最近才知道的,之前是全部复制到编辑器,自己加引号,很痛苦。一个完成的header信息如下
headers = {
"5e007f": "03e41690a6f9b00fe7108532eaf06c40",
"accept": "text/javascript, text/html, application/xml, text/xml, */*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded",
"csht": "",
"pre": "5048a2e6-a9f355-574ae476-44a8ba14-f62ce597371e",
"priority": "u=1, i",
"sec-ch-ua": "Not)A;Brand;v=99, Google Chrome;v=127, Chromium;v=127",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "Windows",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"w": "2",
"x-requested-with": "XMLHttpRequest",
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
'cookie': 'QN1=000150800758637f54988a57;' 这里少一点,不然太多了,反正也是没有用的信息,大家清楚意思就行
}
通过这个之后请求的结果就是一个http的结果,打印上面的response会输出 200的结果
但是这个结果我们是看不到的,所以需要转换成文件,只需要response.text,这个方法就行。这样返会的结果就会变成字符串。如果是网页的会变成源代码,就是html标记,如果是接口请求可以将它转换为dict字典的形式进行访问。
如果是html标记,需要使用xpath进行节点匹配,获取节点里面的信息。先将文件变为节点来处理
from lxml import etree 引入lxml里面etree
html= etree.fromstring(xml_string) 解析为html
之后可以直接对html进行xpath的操作
html.xpath('//div[@class="J_flightList"]/div')
可以通过标签上面的class或者id进行定位,xpath的一些操作不过介绍。这里进行说明一个坑,也是我在使用中遇到的。因为在使用xpaht时,大部分都是通过class进行识别的,如果相同的元素有多个,那么获取的节点信息是一个列表。当时我认为节点已经分成了两个,所以在遍历节点进行操作的时候,想当然的认为操作的当前节点,但是在获取信息获取的是从根节点的信息,也就是在一个节点上获取多个节点的信息,但是我在打印当前节点文本的没有看到获取的额外内容。经过资料发现,使用xpath虽然可以获取节点列表,但是对列表中节点再次进行操作的时候,其实是对整个html操作,需要加上当前节点的信息
html.xpath('.//div[@class="J_flightList"]/div')
这个点就是代表当前节点的意思,这个不会直接操作到根节点。那么之后就可以使用text()获取文本信息了
html.xpath('//div[@class="J_flightList"]/div/text()')
这些是静态网页的过程。如果是请求,那么是需要直接访问这个请求的地址,看下这个请求是get,post请求及携带的参数等,通过将参数转成json或者form表单的形式,获取返回结果。
返回的结果一目了然,之后就像操作dict一样去获取深度信息就可以了。