服务端渲染:
客户端渲染:
所以本质上,两种渲染方式对爬取各有优劣。
这个headers指的是html的头信息,这部分信息是给浏览器看的。打开一个网页,例如x瓣电影。按 F12抓包,刷新一下页面,这个headers部分就是了。
我们下面就要用到这个User-Agent,它表示这个请求来自哪里,图中蓝框表示来自浏览器。很多网页最基础的一个反爬方法就是判断你的User-Agent是什么,如果来自程序,就拦截不给返回。
例如我们来请求一下上面的页面。
import requests
url="https://movie.douban.com/top250"
resp = requests.get(url=url)
print(resp.text)
返回结果为空,说明请求被拦截了
这里我们先看看代码的请求头是什么样的?
import requests
url="https://movie.douban.com/top250"
resp = requests.get(url=url)
# resp.request表示发出的请求,再.headers表示这个请求的headers信息
print(resp.request.headers)
很明显这是个python程序
我们来修改headers,假装自己是浏览器(一个简单的小反爬)
import requests
url="https://movie.douban.com/top250"
# 把F12中的User-Agent信息拷过来,改成字典格式
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36"}
# 把字典传入headers参数即可
resp = requests.get(url=url,headers=headers)
print(resp.request.headers)
print(resp.text)
看这次的User-Agent信息
网页返回结果很长,我们简单搜一个电影名,能看到就OK
不少网页都会有这个请求头检测功能,所以headers参数其实也可以作为常规参数加上,避免每次再去处理。
我们换一个小说网页 https://www.qu-la.com/
假如我要搜一本小说,更好的方式是把书名作为一个变量,例如
https://so.biqusoso.com/s2.php?ie=utf-8&siteid=qu-la.com&q=探虚陵
格式是 url = f'xxx网址其他部分xxx{变量名}'
import requests # 导入requests包
book = "探虚陵"
url = f'https://so.biqusoso.com/s2.php?ie=utf-8&siteid=qu-la.com&q={book}'
response = requests.get(url) # Get方式获取网页数据
print(response.request.url)
# 最后记得关掉response
response.close()
那串乱码不用管它,从网页直接复制中文也会变成这样,点击可以访问的
F12 还可以查看输入的参数,注意?后面的都是入参(黄色部分)
https://so.biqusoso.com/s2.php?ie=utf-8&siteid=qu-la.com&q=探虚陵
所以可以看到,这个网页一共有3个参数
对于搜索框输入的、网页url里直接写的,基本上都是get格式的。如果要确认的话可以抓包查看。
get请求的传参方法是:
将Query String Parameters部分的参数全部复制出来,组一个字典,然后通过get方法的params参数传进去。
book = "探虚陵"
myParams = {
"ie": "utf-8",
"siteid": "qu-la.com",
"q": book
}
代码如下
import requests # 导入requests包
book = "探虚陵"
# 获取到的参数
myParams = {
"ie": "utf-8",
"siteid": "qu-la.com",
"q": book
}
#url,只要问号前面部分
url = 'https://so.biqusoso.com/s2.php'
# Get方式获取网页数据,params传参
response = requests.get(url=url,params=myParams)
# 查看拼出来的链接结果
print(response.request.url)
# 最后记得关掉response
response.close()
输出结果是一样的
post请求通常传一些机密性比较高的内容。这个案例稍微复杂一点,主要复杂在抓包的部分,这次用百度翻译的网页做例子
F12打开抓包工具,刷新,在我们什么都没输的时候有3个页面。选all的话页面会太多,数据相关的主要在Fetch/XHR部分,所以直接点到这部分。
输入一个dog(注意要用英文输入法,否则新的页面不会出来)
新增了好多页面,怎么找哪一个有dog的翻译数据?
逐个点点新增的页面,选中preview,看看页面效果。你会发现有一个sug的内容跟下拉框是一样的,这就是我们要找的数据。
如果打开源码看看,你会发现没有搜索出来的“狗”这个关键字
其实这就是前面提到的客户端渲染的网页。它的源码中只有一个框架,数据是在第二次请求的时候传入的(输入dog,才新传入sug中的数据)。
点headers,可以看到这是个post类型的请求,并且真正的url是https://fanyi.baidu.com/sug
它的入参也在Payload页面,就一个 kw:dog
这样我们需要的关键元素就齐活了:
import requests
# 待查单词
word = 'dog'
# 入参字典
myParams = {
"kw": word
}
url = 'https://fanyi.baidu.com/sug'
# Get方式获取网页数据,params传参
response = requests.post(url=url,params=myParams)
# 查看返回数据
print(response.json())
response.close()
代码跟之前get其实没太大区别,主要是两点:
5. 一个常用案例——传参翻页
上面的功能其实还不太常用,最常用的可以处理翻页问题,来看这个网页,随便找一本小说 https://m.gdedu.tv/dir/73358/?page=2&sort=asc
改一下代码,循环page参数(这个页数比较简单,可以直接看出来的)
import requests
#url,只要问号前面部分
url = 'https://m.gdedu.tv/dir/73358/'
for i in range(1,5):
# 获取到的参数
myParams = {
"page": i,
"sort": "arc"
}
# Get方式获取网页数据,params传参
response = requests.get(url,params=myParams)
# 查看拼出来的链接结果
print(response.request.url)
# 最后记得关掉response
response.close()
查看拼出来的链接
都是可以打开的 https://m.gdedu.tv/dir/73358/?page=1&sort=arc
1. 随便点进去一个链接,里面还有很多具体章节,怎么爬取具体章节信息?
这里先简单提一下,点击查看源码,你会看到每个标题都是一个超链接,后面我们会学习怎么提取这些超链接和章节名。
再随便打开一章,你会发现每章里面也是有分页的
再用F12获取下对应的参数,找啊找,发现没有对应的page参数。很明显这个页数就在链接里了。
2. 这种情况要怎么判断每章有多少页,下页链接是什么呢?
其实同理,这个“下一章”也有自己对应的链接
查看源码,搜729776,这玩意在JavaScript标签里。但是没关系,只要你会匹配上面的超链接,你自然就会匹配下面这个,具体我们以后再看~
参考:B站课程 P1-P16
2021年最新Python爬虫教程+实战项目案例(最新录制)_哔哩哔哩_bilibili