抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

写的这个小爬虫程序主要是应用requests库和lxml包的etree库,简单介绍一下。

1. 关于爬虫

百度百科对于爬虫的定义是,网络爬虫(又被称为网页蜘蛛、网络机器人,在 FOAF 社区中,经常被称为网页追逐者),是一种按照一定的规则,自动抓取互联网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。

我们只需要知道爬虫的作用是抓取网页的信息,其实现在互联网上充斥着大量的爬虫,包括不局限于火车票抢票软件,各种实时数据分析网站等等,本质上都是发起大量的http请求获得信息。爬虫技术的滥用会导致目标网站在短时间内收到大量的访问请求,进而导致服务器瘫痪,相当于是ddos攻击了。但是爬虫的便利性是不可否认的,尤其是批量操作数据和获取信息,比如批量下载我们需要的文献等等。犯罪的永远是凶手而不是工具,我们在合法的范围内应用好工具,能为我们生活提供非常大的便利。

知其然知其所以然,了解这个技术的最好方法是自己去学,因此写了这个小爬虫程序。为什么拿微博热搜来练手呢,因为微博热搜网页结构非常简单明了,很容易上手……

1.1 requests

requests是最常用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到,专门用于发送HTTP请求。说白了requests最大的作用就是发起http请求,返回我们需要的网页数据,所谓爬虫就是从网页上抓取和整理我们需要的公开的信息,对于非公开的信息抓取是违法的

requests请求方式:

1
2
3
4
5
6
7
requests.get(url, kwargs):     发送GET请求
requests.post(url, kwargs): 发送POST请求
requests.put(url, kwargs): 发送PUT请求
requests.delete(url, kwargs): 发送DELETE请求
requests.head(url, kwargs): 发送head请求
erquests.options(url, kwargs): 发送options请求
这些请求方法的参数和用法一致,必选参数为url,其他参数为可选参数

1.2 etree

lxml的etree是从上面requests返回的html源码中提取信息用的,我们可以通过xpath解析网页的dom树,从中获取我们需要的元素和内容。

主要用的也就是etree.HTML(),可以用来解析字符串格式的html文档对象,更方便对我们需要的元素和对象进行抓取,后面演示会说到。

2. 代码和结果展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
from lxml import etree
import time

url = 'https://s.weibo.com/top/summary/'
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
'cookie': "UOR=www.baidu.com,s.weibo.com,www.baidu.com; SINAGLOBAL=2417808258422.6777.1651037395174; _s_tentry=-; Apache=9947874618898.105.1651493077297; ULV=1651493077318:2:1:1:9947874618898.105.1651493077297:1651037395190; PC_TOKEN=04cd3c070b; login_sid_t=80fe8e3820060c4330191a42b71357dd; cross_origin_proto=SSL; ALF=1683032497; SSOLoginState=1651496497; SUB=_2A25Pa6ZiDeRhGeFL6lAT-CzMyj-IHXVsAJCqrDV8PUNbmtB-LUjdkW9NQm3k0nVgyW6LFmyhR5luy-dtvVNK1VjC; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WWTcwdUO8qo5ZVwP9-2e8C.5JpX5KzhUgL.FoMfeKzE1hz7eKe2dJLoIp7LxKML1KBLBKnLxKqL1hnLBoMNSK2EeonEeh20"}

resp = requests.get(url, headers=header)
resp1 = resp.content.decode(encoding='utf-8')
resp2 = etree.HTML(resp1)
title = resp2.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td/a/text()')
clout = resp2.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td/span/text()')
addresses = resp2.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td/a/@href')

print(time.strftime("%F,%R")+'\n50条实时微博热搜\n'+'\n排列方式:序号+关键词+热度\n')
for i in range(51):
if i == 0:
print(''.join('置顶'+'\t'+title[i]+'\n'+'https://s.weibo.com'+addresses[i]), '\n')
else:
print(''.join(str(i)+'\t'+title[i]+'\t'+clout[i-1]+'\n'+'https://s.weibo.com'+addresses[i]), '\n')

未对代码进行封装,源代码就这么十几行,实现的结果是,执行一次就在当前终端屏幕上输出实时的50条微博热搜话题,并显示序号和热度,每条热搜话题下一行生成微博超链接。

3. 代码详解

建立python脚本,导入模块这步不解释了。

url是我们要抓取信息的网站地址,这个很好理解。header是我们调用requests模块需要的一个重要参数,里面提供了我们访问需要的认证信息cookie,http请求本身是无状态的,网站无法确认前一次发出请求的人和后一次发出请求的人是否为同一人,因此需要让网站记住我们的登录信息cookie以响应我们的请求。没有header可能无法返回网页信息,那这一大堆东西是怎么来的呢?需要我们审查网页元素。

3.1 获得cookie和user-agent

打开微博热搜首页,登录微博,随便什么空白的地方右键,点击检查,找到network(网络)。

上面的为网页元素,日志控制台,网络,资源,性能和内存等等标签,下面的就是对应的内容,往往点击第一个总结类的文件可以获得request headers信息,这里面最重要的两个信息:cookie和User-Agent

将cookie和user-agent内容全部写到header变量中,这样每次访问网站就带上了我们唯一的标志信息

resp = requests.get(url, headers=header) 访问目标网址,返回的html源码赋值给resp,然而我们看不到返回的值是怎么样的,什么类型的,这里我就要介绍一下vscode的AREPL插件了。

3.2 AREPL查看变量和审查网站元素

前面介绍vscode插件说过,AREPL可以实时打印出当前的变量信息而不需要运行代码,极大地方便了我们查看返回的值和信息,知道每一行代码发挥了什么作用。

我们看一下自定义的resp变量是什么:

status_code值为200,很明显成功返回了html源码信息,但是点开来看却得不到我们需要的网页文字信息,因为还没有进行解码。我们可以看到编码方式是UTF-8,自然而然的,我们就要对resp变量值进行对应的UTF-8解码,也就是后面的代码resp1 = resp.content.decode(encoding='utf-8'),这里注意一点要用content不能用text

再来点开看看解码后的resp1:

如果有点html基础的话会发现,怎么样,是不是很熟悉!没错!这就是我们在审查网页元素获得的网页的前端结构,这里包括了所有的网页信息,再也不用点开原网站一个一个元素去找啦!(就比如我这小破站的网页元素看地我脑瓜子嗡嗡的)这里可以很轻易地看到各个节点信息,极大方便了我写上面的爬虫代码。

这里我需要三个信息,热搜的标题、热度和网址,我们来展开看一看网页结构:

像洋葱一样一层一层拨开网页结构,我们可以清楚地看到table/tbody/tr/td/a节点的内容是微博热搜标题,a这个节点的标签href就是网址,table/tbody/tr/td/span节点的内容就是热度,至此,网页结构一清二楚,我们要做的就是把信息提取出来,提取的方式就是etree解析这个字符串格式的html文档,生成对应的元素路径。

3.3 解析html文档

resp2 = etree.HTML(resp1)就是用来解析字符串格式的HTML文档对象的,将传进去的字符串转变成元素对象

转换后的resp2如下,我们可以看到每个节点都被转换成了_Element对象:

接下来就是顺理成章地用xpath寻找元素路径,将对应内容提取出来,我的元素路径中应用了正则表达式,这里也不解释了。

最后可以将提取出来的三个信息一一打印出来看看是否有问题(AREPL插件真的立大功),有了信息接下来就是整理和排版,那就是print函数和循环语句的基本用法了。虽然python中的print函数和循环语句与R或者linux中略有不同,这个基础知识这里也不再赘述。

唯一我觉得需要注意的是,range() 函数提供的是0-51的整数;官网置顶的微博没有热度显示,所以我写了一个if判断语句区别;排版的时候注意转义字符,其他都是细节微调部分,怎么美观怎么顺眼怎么来。

4. 总结

因为这个网页没有做反爬(或许是我没注意到)手段,至少我获取这些公开信息还是没有遇到阻碍的,这也是最最简单的一个爬虫脚本了,调用第三方模块,解析网页,最后提取信息和整理,就是这么简单也很好理解。

我最近还接触到一个明日方舟抽卡记录汇总的小程序,我看了下小程序的方法,猜测这类程序也是类似的爬虫程序。先登录官方网站,需要你输入一个网址,提供token_by_cookie这个值,这个值在network标签中能找到,并且能发现resquest url就是获取token_by_cookie值的网站。

获得这个token之后,我们可以看到抽卡记录可以通过另一个需要token的网址中直接获取,明日方舟的抽卡记录只能保存10页,因此,只需要输入token,直接更改page值1-10,就能获得详尽的抽卡信息。而做成好看的图表也无非是把爬虫程序和作图程序结合一下,封装,最后在小程序调用,思路就是这样的。

同时也能发现,如果我们提供token值给别人,除了抽卡记录以外,还能提取我们的充值信息和源石消费信息等等这类隐私信息。要掌握隐私信息无非是程序的作者想不想做的问题,毕竟还是把隐私信息握在自己手里比较好。

学习就是学习这些技术的思路并为自己所用。

欢迎小伙伴们留言评论~