post 爬虫request_真·从零开始使用Requests制作简单爬虫

Requests是Python的一个HTTP客户端库,提供简洁易用的API进行网页内容的获取。相较于urllib,Requests更易理解和使用。本文介绍了Requests的基本用法,包括GET和POST请求,以及处理响应内容。通过示例展示了如何使用Requests进行网页抓取,同时讨论了爬虫可能遇到的问题,如防爬机制和编码问题,并给出了解决方案。
摘要由CSDN通过智能技术生成

Requests是什么?

我个人理解的是,Requests是一个基于python的urllib模块的封装包。对比与python自带的urllib模块,requests的代码理解起来更人性化、更流畅(不过这个特点慢慢被urllib3赶上了)。

我可以用Requests做什么?

见名释义,Requests就是用来请求网络资源用的,例如访问网址,下载视频等。早期很多python爬虫都是基于Requests来实现的,我曾经用Requests做过多个爬虫以及刷投票的爬虫,本文就带大家做一个最简单的爬虫,从0学会使用Requests。这里着重强调一下:我反对大家用爬虫去做任何违法的事,爬虫写得爽,监狱进得早(严肃脸)。

为什么说是早期的爬虫呢?因为现在python的爬虫工具越来越多、越来越强大,Requests需要大量的代码才能实现的功能,对于scapy这种爬虫工具来说不过几行代码的事,所以大家慢慢也不再使用Requests做爬虫。但这个不碍于你学习Requests,并领略他的有趣之处。

安装Requests

pip install requests

这里注意不要漏了Requests最后的s,因为Request是另外一个库

检验是否安装成功

打开CMD,输入python,随后输入

import requests

按回车,如果没有报错信息,则代表已经安装好了

一般报错信息为:ImportError: No module named requests

Requests的基础用法

访问一个网页

r = requests.get('https://www.jianshu.com/p/a82e76881121')

print (r.content) #打印获得网页内容。你也可以使用r.text的方式

一般我们使用Requests的时候,只会用到get或者post两种方式。

简单的科普一下:get的请求方式一般是不附带请求表单。如果进行请求直接附带在链接后类似http://x.x.com?id=1

post的方式一般是附带请求表单,不会展示在链接后

附带w3school-get以及post的比较

返回的信息

403代表的是禁止访问。我们可以通过r.status_code来看返回的访问码

这个码有什么用呢?以前我也觉得没啥用,当有次我在连续爬取某个网站的内容并保存在本地,执行完后,我随机抽看第1000+个的文件,发现后续保存的内容都有问题,因为中途爬虫被识别出来了,后续保存的信息都是错误的。之后我加入了code的判断->本次爬取获得的code跟上次获得的不一样并且不是200,代表爬虫不再适用,就会停止爬虫并报警。

print (r.status_code)

#附带基本的code含义

#200 正常响应

#302 重定向

#403 禁止访问

#404 没有这个网址

#500 服务器没有响应

#502 服务器没有响应

现在一般的网站都有防爬虫机制,所以我们需要给爬虫制作一个user agent,来伪装成一个浏览器

我有一个文件保存了1000+个不同浏览器的user agent,但简书不支持上传附件。为什么要这么多?以后你就知道了

userAgent = "Mozilla/5.0 (Linux; Android 6.0; PLK-AL10 Build/HONORPLK-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043305 Safari/537.36 MicroMessenger/6.5.6.1020 NetType/WIFI Language/zh_CN"

headers = {

'User-Agent' : userAgent #伪装成火狐的手机浏览器

}

r = requests.get('https://www.jianshu.com/p/a82e76881121',headers = headers)

print (r.content)

正确获得了网页内容

headers是告诉服务器你是谁,你从什么网页过来,你做了什么等,headers的内容不单只有一个user-agent,可以通过在Chrome"右键"->“检查”->"网络",点击某一个请求来看当前的headers是什么,然后把程序请求的headers变成浏览器的即可

怎样把获得的内容提取出你需要的信息,一般get获得的方式都是以网页内容为主,你可以使用正则匹配,或者多次切割字符串的方式来获取。如果获取的是json数据,那就可以直接用访问json的方式获取。

一般值得爬的网站,类似小说网等,他们的链接都是有一定的规律的,于是我们通过自动化去生成链接的方式,让程序不断执行上面的get方式,然后保存获得的。

向网站提交表单(POST)

#并不能正确登录,只是做一个简单的例子

#data对象是你要提交的数据,key和value

r = requests.post('https://accounts.douban.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'}

其实post和get在Requests上区别并不大,所以并不细讲post。什么时候用get,什么时候用post不是取决于你,而是取决于服务器对当前链接是采用get还是post,利用查看header的方式可获得请求的方式。

接下来我爬取来展示一下整个流程,以及讲解一下里面的注意地方

打开网站

找到链接间的规律

发现下一章地址就是当前章的地址加1。另外,这个网站并没有做防爬限制,所以大家可以很开心的开始爬,是的就这么简单就做好一个爬虫了。

import requests, time

url = 'http://www.xbiquge.la/1/1693/%d.html' #把链接不变的地方构造出来,%d代表的是把这个位置预留出来,之后填补数字进去

thisHerf = 1269354 #当前页面的地址

filename = '第%d章.txt' #保存成文本,也是预留一个位置之后填补数字

n = 1 #用来保存文章的时候填充章节数

while 1:

r = request.get(url%thisHerf) #获取对应页面内容,%代表的是把数字放到%d这个位置。

thisHerf += 1 #下一个页面的地址 # 当前地址加1,获取下一个地址

with open (filename % n, 'w') as f: #把获取到的网页内容保存成txt文件。

f.write(r.content) #这里有一个字符问题,大家可以自行研究一下

n += 1 #下一个章节数

time.sleep(3) #停止3秒再爬下一章,做个好人

除了%d之外,还有%s,%c等,具体大家可以百度一下占位符即可。

with open里的参数给大家一个参考:

r :只能读已存在的文件;

r+:可读可写,不会创建不存在的文件。从顶部开始写,会覆盖之前此位置的内容;

w+ :可读可写,如果文件存在,则覆盖整个文件不存在则创建;

w :只能写,覆盖整个文件,不存在则创建;

a: 只能写,从文件底部添加内容,不存在则创建;

a+: 可读可写,从文件顶部读取内容,从文件底部添加内容,不存在则创建

well,本来不想告诉大家的,其实这个脚本是有问题的XD。问题如下:

保存这种网页编码本来就是比较反人类,正常人类无法阅读,需要二次处理字符问题。

2.到了一定的章节数,网址其实变化了,跳跃了一大段(小说网站通常都这样),不再连续了。也就是说,后续下载的都是错的文章

那我们那要怎么解决这些问题呢?请保持好奇心,继续往下看

思路

一、文章转码,正确显示文章

二、找到“下一章”这3个字的标签,获取它对应的链接

不再是构建链接的方式,而是获取下一章链接的方式

一、文章转码,正确显示文章

s = str(r.content, 'utf8')

print (s)

加这句前:

服用前

加了之后:

服用后

二、找到“下一章”这3个字的标签,获取它对应的链接

1.找到“下一章”的一种方法

可以通过切割的方式。所谓切割方式,就是根据你想要的字符,在出现该字符的地方切一刀(切多少刀可以由你自己决定)。随后根据获得的内容继续切割,直到获得所需要的字符串。

keyWord = '下一章'

#方法一:切割大法,只保留把“下一章”前的内容

s1 = s.split('下一章')[0] #简单理解split的作用是将“下一章”作为切割点,把字符串切成两块,0代表只保留第一块,1代表第二块

print (s1)#看看有啥

展示末尾部分截图

切割后的结果末尾

很明显了,就是把“章节目录”后的那部分切割好就行了

#这里我一步到位切割了

nextHref = s1.split('章节目录')[1].split('href="')[1].split('">')[0]

print (nextHref)

# 结果输出:/1/1693/1269356.html

split获得的是列表,所以采用[0]、[1]的方式提取。我们这里没有指定切割多少刀,默认只要出现"章节目录"的地方都切一刀,所以split有时候会获得多个元素。附上split的用法

2.找“下一章”的另一种方法

用正则匹配的方式定位并获取对应的内容

keyWord = '下一章'

#方法一:匹配大法,直接寻找“下一章”的标签

import re

#compile里的是正则表达式,具体语法百度就好.

nextHref = re.compile(r'(?<=章节目录 → 下一章)')

l = nextHref.findall(s) #用findall的方式,得到的是列表形式

print (nextHref) # ['/1/1693/1269356.html', '/1/1693/1269356.html']

#提取出来就可以用了

python的re模块不支持变长的后发断言,?<=以及?=后都需要有定长匹配,不然可以直接用(?<=章节目录.*? href=").*?(?=">下一章)效果更佳

整合代码

等等,为什么没有提取正文内容的讲解0.0?因为提取正文内容这部分是与提取“下一章”链接的用法是一致的。这里我建议大家直接使用split就可以了

其实不提取也不影响阅读,要更个性化的用户体验就需要自己动手了XD

没有提取正文,直接展示整个文章

import requests, time, re

# host用于跟我们获得下一章的链接组装成正确的下一章链接

host = 'http://www.xbiquge.la/'

targetHref = 'http://www.xbiquge.la/1/1693/1269354.html'# 第一章的地址

# 保存成文本,也是预留一个位置之后填补数字

filename = '第%d章.txt'

n = 1 # 用来保存文章的时候填充章节数

while 1:

r = requests.get(targetHref) # 获取对应页面内容,%代表的是把数字放到%d这个位置。

# 对文章内容进行转码

s = str(r.content, 'utf8')

# 找到下一章的方法一

#s1 = s.split('下一章')[0]

#nextHref = s1.split('章节目录')[1].split('href="')[1].split('">')[0]

# 找到下一章的方法二

nextHrefRgx = re.compile(r'(?<=章节目录 → 下一章)')

l = nextHrefRgx.findall(s) #用findall的方式,得到的是列表形式

# 组装下一章的链接并赋值给targetHref

targetHref = host + l[0]

with open (filename % n, 'w') as f: #把获取到的网页内容保存成txt文件。

f.write(s) # 把已转码的内容写入

n += 1 #下一个章节数

time.sleep(3) #停止3秒再爬下一章,做个好人

部分结果截图

代码还有个地方没有完善,没有跳出这个循环的break语句。大家可以自行思考一下如何控制跳出循环

That‘s all,Thank you for reading it

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值