Python爬虫爬取网页数据出现特例(python爬取网页指定内容)
python爬取网页数据是返回空列表,errno:1?
正好我也在做这题。
如果把%22替换为""的话,就会出现errno:1的情况,也就是没有novel数据,只需要url = 原来的链接就能得到正确的答案了
由于我是新手,感觉挺怪的不知道其原理
如何用Python爬虫抓取网页内容?
爬虫流程
其实把网络爬虫抽象开来看,它无外乎包含如下几个步骤
模拟请求网页。模拟浏览器,打开目标网站。
获取数据。打开网站之后,就可以自动化的获取我们所需要的网站数据。
保存数据。拿到数据之后,需要持久化到本地文件或者数据库等存储设备中。
那么我们该如何使用 Python 来编写自己的爬虫程序呢,在这里我要重点介绍一个 Python 库:Requests。
Requests 使用
Requests 库是 Python 中发起 HTTP 请求的库,使用非常方便简单。
模拟发送 HTTP 请求
发送 GET 请求
当我们用浏览器打开豆瓣首页时,其实发送的最原始的请求就是 GET 请求
import requests
res = requests.get('')
print(res)
print(type(res))
Response [200]
class 'requests.models.Response'
如何用python抓取网页特定内容
最简单可以用urllib,python2.x和python3.x的用法不同,以python2.x为例:
import?urllib
html?=?urllib.open(url)
text?=?html.read()
复杂些可以用requests库,支持各种请求类型,支持cookies,header等
再复杂些的可以用selenium,支持抓取javascript产生的文本
我设计了简单的爬虫闯关网站
新手如果能自己把三关闯过,相信一定会有所收获。
题解在课程里有提到
python爬虫抓取到的数据用网页打开时是乱码,怎么解决
写爬虫是经常会遇到这样的问题,这种问题很显然是编码问题,解决的方法其实也不难。
你可以用下面的两个方法来解决你的编码问题:
第一种是,通过浏览器打开你写的html之后,找到浏览器中的文字编码修改,将编码改为Unicode编码,即可修复。
第二种方法是修改你的前端代码:在你的代码output_html方法中,规定网页的文字编码即可
python爬取大量数据(百万级)
当用python爬取大量网页获取想要的数据时,最重要的问题是爬虫中断问题,python这种脚本语言,一中断
进程就会退出,怎么在中断后继续上次爬取的任务就至关重要了。这里就重点剖析这个中断问题。
第一个问题: 简单点的用动态代理池就能解决,在爬取大量数据的时候,为了速度不受影响,建议使用一些缓
存的中间件将有效的代理 ip 缓存起来,并定时更新。这里推荐 github 这个仓库
, 它会做ip有效性验证并将 ip 放入 redis ,不过实现过于复杂
了,还用到了 db ,个人觉得最好自己修改一下。困难点的就是它会使用别的请求来进行判断当前的ip是否
是爬虫,当我们过于聚焦我们的爬虫请求而忽略了其他的请求时,可能就会被服务器判定为爬虫,进而这个ip
会被列入黑名单,而且你换了ip一样也会卡死在这里。这种方式呢,简单点就用 selenium + chrome 一个一个
去爬,不过速度太慢了。还是自己去分析吧,也不会过复杂的。
第二个问题: 网络连接超时是大概率会遇到的问题,有可能是在爬取的时候本地网络波动,也有可能是爬
取的服务端对ip做了限制,在爬取到了一定量级的时候做一些延迟的操作,使得一些通用的 http 库超时
( urllib )。不过如果是服务端动的手脚一般延迟不会太高,我们只需要人为的设置一个高一点的
timeout 即可(30 秒),最好在爬取开始的时候就对我们要用的爬取库进行一层封装,通用起来才好改
动。
第三个问题: 在解析大量静态页面的时候,有些静态页面的解析规则不一样,所以我们就必须得做好断点
续爬的准备了( PS : 如果简单的忽略错误可能会导致大量数据的丢失,这就不明智了)。那么在调试的过
程中断点续爬有个解决方案,就是生产者和消费者分离,生产者就是产生待爬 url 的爬虫,消费者就是爬取
最终数据的爬虫。最终解析数据就是消费者爬虫了。他们通过消息中间件连接,生产者往消息中间件发送待
爬取的目标信息,消费者从里面取就行了,还间接的实现了个分布式爬取功能。由于现在的消费中间件都有
ack 机制,一个消费者爬取链接失败会导致消息消费失败,进而分配给其他消费者消费。所以消息丢失的
概率极低。不过这里还有个 tips , 消费者的消费超时时间不能太长,会导致消息释放不及时。还有要开启
消息中间价的数据持久化功能,不然消息产生过多而消费不及时会撑爆机器内存。那样就得不偿失了。
第四个问题: 这种情况只能 try except catch 住了,不好解决,如果单独分析的话会耗费点时间。但在
大部分数据 (99%) 都正常的情况下就这条不正常抛弃就行了。主要有了第三个问题的解决方案再出现这
种偶尔中断的问就方便多了。
希望能帮到各位。
python爬虫爬取只显示10个
一个借口几万条数据但是只返回十条_爬虫实践之爬取10000条菜谱数据
2020-12-03 06:37:24
weixin_39990029
码龄5年
关注
be22f93fc7bbc7cbdd62166579a1fd22.png
爬虫实践之XX行代码爬取10000菜谱数据
什么是爬虫
爬虫:又叫做 网络蜘蛛,是一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。
点击这里了解Python爬虫介绍
如何合法地爬虫
有些网站不允许网络爬虫,或是对可爬取的内容做了限制,一个网站的爬虫协议可通过访问该网站的robots.txt文件获得
以豆瓣网为例
访问该网址(),可了解到豆瓣的爬虫协议如下
1fe03008a450885dc6da49785543e75c.png
可以看到,豆瓣对于不同的访问者有不同的访问限制,其中对于用户名为 Wandoujia Spider的访问者,豆瓣不允许访问。
我用到的菜谱网站对爬虫无限制,所以爬虫是合法的。
e4025d9f5d8b96388efa942e0255d1f9.png
本篇特色
连续爬取10000个网页
引入第三方库
import requests #发送请求
import re #正则表达式,用于提取网页数据
import winsound #提醒程序运行结束
import time #计算程序运行时间
如果没有安装这些第三方库,可以在命令提示符中输入如下代码,进行下载
pip install requests,re,winsound,time
爬虫的三个步骤
获取要爬取的所有网页的网址
提取网页内容中的有用信息
信息导出
每个步骤对应一个函数
Step_1 获取要爬取的所有网页的网址
首先我们打开该网址,查看它的源代码
0f0eb8b89c9bf17460bca4d47f017bab.png
365621d25c80f92834853350c083a545.png
网页源代码
观察发现每道菜对应的网址在这个目录下
9d729b843df3a746d70ea7af31a1d962.png
用正则表达式获得该网址,写入列表中
由于每一个网页只有十道菜,点击下一页后发现网页的变化规律为换页时网址只有数字改变
d342d8422e16c48c9600a47a45a6d1c9.png
可以看到最多有1000页,也就是有10000道菜
fb279b42fcdd3cecf7cda79ba4a8ae53.png
使用循环,将每一页的菜对应的网址都写入列表,每一次写入时写入一行列表,多次写入后,形成一个二维的列表,前两页的菜谱网址在二维列表中显示如下:
31e3755dc8b45ec6f4dac3c05f261539.png
代码如下
all_url = [] #创建一个数组用于存储网页地址
def get_all_url(n): #这个函数用于获得网页中的菜的全部网址
if(n==1):
url = ""
else:
url=''%n #%s相当于C语言中的%s,表示格式化一个对象为字符,同理%d表示格式化一个对象为整数
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36" }
response = requests.get(url,headers=headers) #访问网页
response.encoding = "utf-8" #设置接收编码格式
pattern = re.compile(r'a target="_blank" href="([a-zA-z]+://[^s]*)"', re.S)
#正则表达式提取网页中的网址,re.S表示在整个文本中进行匹配,如果不加re.S,将只在一行进行匹配
result = pattern.findall(response.text) #获取的网页结果存储到result里
all_url.append(result[0:10])#由于每页只有十道菜,result中只有前十条对应的是菜的网址,故我们只添加前十条
return all_url #作为返回值返回这个列表
关于headers的说明
在使用python爬虫爬取数据的时候,经常会遇到一些网站的反爬虫措施,一般就是针对于headers中的User-Agent,如果没有对headers进行设置,User-Agent会声明自己是python脚本,而如果网站有反爬虫的想法的话,必然会拒绝这样的连接。而修改headers可以将自己的爬虫脚本伪装成浏览器的正常访问,来避免这一问题。 点击这里了解详情
关于编码格式utf-8 的说明
utf-8,可以编码中文,大部分python编译器都默认编码方式为utf-8 点击这里了解详情
Step_2 提取网页中的有用信息
打开一道菜的网址,查看源代码,寻找我们需要的信息在哪里,然后用正则表达式获取,流程与上个函数获取网址相同
主辅料信息在这里
c0ddfd3110775bb8b71759f6927f26d4.png
特征信息在这里(包括做法和口味)
38c99c1a51137debcafe38ae3122e19a.png
def get_info(resp,output):
name_pattern = re.compile(r'h1(.*)/h1')# 正则表达式获取菜名信息
food_pattern = re.compile(r'span class="t"(.*)/spanspan class="a"(.*)/span/a/div')# 正则表达式获得主料信息
fixing_pattern = re.compile(r'div class="c_mtr_li"span class="t1"(.*)/spanspan class="a"(.*)/span/div') # 正则表达式获得辅料信息
fearture1_pattern = re.compile(r'div class="cpargs cpargs2"div class="i"/div(.)/div')# 正则表达式获得特征_1
fearture2_pattern = re.compile(r'div class="cpargs cpargs3"div class="i"/div(.*)/div')# 正则表达式获得特征_2
name = name_pattern.findall(resp.text) # 提取菜名信息
food = food_pattern.findall(resp.text)# 提取主料信息
fixing = fixing_pattern.findall(resp.text)#提取辅料信息
fearture1 = fearture1_pattern.findall(resp.text) #提取特征_1
fearture2 = fearture2_pattern.findall(resp.text)#提取特征_2
output.write(str(name))#将菜名写入output文件,write函数不能写int类型的参数,所以使用str()转化
output.write('t')#进入下一个单元格
output.write(str(fearture1))#将特征_1写入output文件
output.write('t')#进入下一个单元格
output.write(str(fearture2))#将特征_2写入output文件
output.write('t')#进入下一个单元格
for i in range(len(food)):
for j in range(len(food[i])):
output.write(str(food[i][j])) #写入主料
output.write('t')
if(len(food)11):
output.write('t'*2*(11-len(food))) #每道菜的主料数目不同,该行代码可使表格内容对齐
for i in range(len(fixing)):
for j in range(len(fixing[i])):
output.write(str(fixing[i][j])) #写入辅料
output.write('t')
output.write('n') #换行
Step_3 信息导出
def spider():
output = open('E:programingpython苏菜_2.xls','w',encoding='utf-8')#创建一个excel文件,编码格式为utf-8
output.write('名称t做法t特色t主料')#写入标题栏
output.write('t'*22)#使内容对齐
output.write('辅料n')#写入标题栏
for i in range(len(all_url)):
for j in range(len(all_url[i])):
url2=all_url[i][j]
response = requests.get(url2)#逐个访问网页,获得数据
response.encoding = "utf-8" #设置接收编码格式
get_info(response,output)#处理数据,提取信息
output.close()#关闭文件
主函数
time_start = time.time()#记录程序开始时间
for i in range(1,2):#逐页获取菜谱网页信息
get_all_url(i)
spider()#进行提取处理并导出
duration = 1000#提示音时长,1000毫秒 = 1秒
freq = 440 #提示音频率
time_end=time.time()#记录程序结束时间
print('totally cost',time_end-time_start)#打印程序运行时间
winsound.Beep(freq,duration*10) #响铃提示程序结束
经实验,爬取10000条代码需要用时3453秒左右
e8b6c8637980d2aef9587711c7084a5f.png
最后获得的数据如下
97a8662cf048844850658aef841e04c3.png
写在后面
我是一个C语言上不了80的小白,全靠某度和某歌东拼西凑我的这个程序,在代码风格与写作等方面存在不可避免地会有一些错误和不足的地方,希望大家多多与我交流,多多批评指教我。