前面学习的爬虫知识都是将页面的数据抓取下来,专业来说也就是 get
数据,而有时候在 get
的同时,还会向后台发送请求数据。
在百度搜索的时候,打开百度搜索的主页 https://www.baidu.com/ ,这一过程是 get
的行为;如果在搜索栏中输入某一个关键字,并点击了 百度一下
,这时候前端会将你的关键词发送到后端中处理,也就是从数据库中提取出与关键词相关的东西,将其展现在页面。这里也是 get
的行为,但是在 get
之前却将关键字发送给了后端。
那么在爬虫中,怎样写代码才能像浏览器一样,向后台请求需要的信息呢?
涉及到 请求数据
的时候,需要经常查看网页给后台请求了那些数据,建议大家使用 firefox
浏览器,对浏览器增加一个新的插件 firebug
。这是一个很好的查看网页源码以及各种网页信息的插件:
安装完毕后,打开 firefox
浏览器,进入百度搜索,然后按下 F12
:
点击 网络
-> JavaScrip
,在输入关键词之前清除 历史记录 和 清空请求列表,然后在百度搜索栏中输入关键字 TTyb|个人网站
,那么网络下面会出现如下情况:
点击 url
前面的 +
号,点击到 参数 的位置,可以看到当输入关键词的时候,百度向后台请求了这些数据:
而点开 头信息 -> 请求头信息 -> Referer ,可以看到网址的构造结构为:
https://www.baidu.com/s? + 请求参数的字段
那么,只要按照上面的网址结构构造 url
,就可以自定义请求数据抓取了。在浏览器中将参数复制下来,构造成一种 json
的格式,即:
postdata = {
'_': 1495027071193,
'bs': "ttyb|个人网站",
'cb': "jQuery110207635110323506591_1495027071143",
'csor': 18,
'json': 1,
'p': 3,
'pbs': "ttyb|个人网站",
'pwd': "ttyb|个人网站",
'req': 2,
'sid': "1432_21085_17001_20927",
'sugmode': 2,
'wd': "ttyb|个人网站"
}
观察看以看到,字段 '_': 1495027071193
代表的是毫秒级的时间戳,这个字段可以在 python
中生成。在 python
中可以用库 import time
来生成时间戳:
import time
nowtime = int(time.time())
但是生成的这个时间戳只是秒级的,及只有 10
位数,而请求数据里面的时间戳是毫秒级别的,有 13
位数,所以这里需要做一个小小的处理。作者这里是生成一个 3
位数的随机数,将其和时间戳拼接起来:
import time
import random
timerandom = random.randint(100, 999)
nowtime = int(time.time())
nowtime + timerandom
时间戳搞定,再看 postdata
里面出现了很多次搜索关键字 ttyb|个人网站
,所以这里可以都换成一个变量 keyword
,这样就能随时的变换搜索的关键词了。
一切准备就绪后,就可以构造抓取函数了。前文提到 requests
库是非常好用的库,在构造 postdata
的时候可以直接传入而不需要转义成 url编码
,主体请求函数为:
html_bytes = requests.get(url, headers=header, params=postdata)
url
为前文提到的结构 https://www.baidu.com/s?
,header
为请求的头部,如果忘记了请看 4.增加头部,postdata
就是前面构造的 postdata
。
def gethtml(url, postdata):
header = {}
# 解析网页
html_bytes = requests.get(url, headers=header, params=postdata)
return html_bytes.content
在代码中调用:
html_bytes = gethtml(url, postdata)
html = html_bytes.decode("utf-8", "ignore")
print(html)
这里可以发现在编码转化的过程中增加了 ignore
,这个是为了预防网页中的编码不一致,因为代码中是想将抓取下来的网页的编码转换为 UTF8
的格式,但是有些网页是多格式混合的,例如还会包含 GBK
、GB2312
等等,如果混合了多种编码格式的网页,在使用 decode("UTF-8")
的时候会报错,而计入了 ignore
后,酒会自动忽略掉其他的编码格式,只是将 UTF-8
格式进行转换。
最后,查看一下抓取的效果:
而且 python
中可以接受输入。这里可以将 keyword
用输入的方式写入:
keyword = input("请输入你要搜索的关键词:")
这样抓取的方式更加灵活多变,是不是很好?!
增加百度翻页的效果,即可以选择抓取第2页、第3页等等