总得前行
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
Scrapy爬虫问题的调试小则
问题解决
问题:
说爬虫程序跑着跑着就会被重定向到verify页面,有时候会报400错误。
思路:
第一反应就是走代理!
步骤:
拿到代码后,发现是scrapy框架写的爬虫。这个框架早几年用过余弦大佬写的“妹子图”网站的爬虫哈哈,但是那会刚入门仅会跑起来scrapy框架。。
第一步,装scrapy,改数据库配置。先跑起来,跑时候发现报错,发现用的webdriver爬取。下载webdriver,更改脚本里调用路径。注意需要绝对路径。ok,一连串的失败,排查发现这个是由于代理导致的。原代码里用了代理。
第二步,找代理。原代码里的代理账号密码等都在,但是就跑不通。起初以为是改了密码,后面发现可能是因为没有在对方代理网站的白名单上加我自己的网络出口。由于是帮忙调试的原因,也由于客户问题,就没有跟其要代理账号密码或者自己去买一个,自己默默的打开百度搜起免费代理。。
这个步骤中浪费了很多时间。首先是找了好多免费网站去抓代理ip,然后写脚本对抓来的ip测试其可用性。这边还有个坑是我用抓到的代理ip去访问我的云服务器,当在我云服务器上收到代理ip请求记录时我认定这个ip代理可用,但是一顿操作下来满心欢喜的整理完代理ip列表,又花了一会时间重写了在scrapy里的代理中间件(原代码里的代理中间件是直接网页获取返回代理ip),然后跑时候发现,一堆报错! 错误显示该网站不可信、该ip存在xxxx问题拒绝访问、跳转到verify页面等等情况。。起初有些错误不能理解,为什么代理访问后显示网站不可信这些报错?这根代理ip有啥关系?一顿百度google后,发现大部分帖子说的就是代理ip问题。。(具体错误细节记得不是太清了,大概是这样)
用免费代理ip问题太多了,然后就放弃这个路线了,然后就想直接买个代理算了。然后就想起直接去源代码里的代理厂家买吧,最起码代理中间件不用调了(原代码里的代理中间件部分ip调用及定时更换的逻辑是现成的)。看了下源代码里的代理中间件,点开了他的代理网站链接,发现这个网站有免费试用哈哈。一顿注册后拿到了代理api,替换到代码里开跑,可以跑起来了,但是没几分钟又开始了跳转到verify页面和夹杂着400状态码。。然后不死心重新跑了几次,期间也调低请求并发数和下载延时、关闭cookie等操作,但是一直都是跑了几分钟就开始跳转到verify页面。。
这会的反应就是是不是网站对这些页面数据有其他保护,就是不允许访问?于是就操起了requests,自己写了点脚本来模拟下爬虫的内容。这边又花了很多时间,因为隔了一天,免费试用的代理过期了,所以又又去找了其他家公司的代理,然后加了webdriver、重写了代理(厂家不一样)和调用机制、详细看爬虫的系列逻辑然后摘取出来到自己脚本里,模拟了三四层的爬取深度代码,将每个请求之间延时5秒等等,最后发现是可以跑出结果的。
然后接着回来看scrapy代码和代理和调试。。
第三步,买代理! 第二步中最终是没有发现scrapy的问题的,然后因为一些沟通原因以为这个小任务结束了,就没有继续测。但是今天突然被问测得怎么样了。。所以决定直接买代理快点测吧。。其实之前中间断了一两天,这两天内也想通了一些事,程序跑着跑着就跳转到verify的问题和频繁400等问题可能是由于代理ip重复了、代理ip过期时间太长即使用次数太多、代理ip不可用、代理ip代理速度太慢、程序开着静态cookie(脚本里调用了自写的cookie中间件,但是在运行中没有做cookie更换)等原因导致的。果然,在结合调低请求并发数、请求延时等配置后,设置代理ip每个ip固定请求2次后即更换后情况好了。虽然还会有被重定向到verify或者出现服务不可达或者超时等错误,但是不像之前满屏都是跳转verify的情况了,随着更换一次或几次代理ip后就又可以恢复正常爬取了! 但是写这篇文章时也突然想到,也有可能有因为我用的不是源代码中使用的代理厂家的原因。
总结:
该爬虫出现的问题可能是由两方面原因导致的。一是由于程序获取到的代理ip重复了、代理ip过期时间太长即使用次数太多、代理ip不可用、代理ip代理速度太慢等代理问题。一方面需要找些大厂家,在代理功能上可靠些;另一方面,自己也需要对拿到的代理ip进行足够的确认、调配与容错等。二是程序用了静态cookie,在运行中又不动态更换导致的被识别。
其他小记
代理ip的调配逻辑
因为之前是调试模式,所以是想到哪写到哪,没有怎么调,所以写的有点乱但是也不想改了。。本来是想着将用过的代理ip加入列表,使用新代理ip时检验下是否重复;每个代理ip请求5次后更换等等的,但是在后面调试过程中都逐渐改低了。在写文章时还发现了代码存在问题哈哈,客官切勿直接使用。。
class HeaderMiddleware(object):
def __init__(self):
self.proxy_ip_use_num = 0
self.proxy_ip_access_num = 0
self.proxy_ips_using = []
self.proxy_ips_used = []
self.ua = UserAgent()
def get_proxy_ip(self):
time.sleep(10)
self.proxy_ips_using = []
resp = requests.get(url='https://proxyapi.horocn.com/api/v2/proxies?order_id=APTU1&num=10&format=text&line_separator=win&user_token=4799b3377c6bd462f20c1b3c')
for i in resp.text.splitlines():
self.proxy_ips_using.append(i.strip())
print(self.proxy_ips_using)
# 请求处理
def process_request(self, request, spider):
request.headers.setdefault("User-Agent", self.ua.random)
request.headers["referer"] = None
if self.proxy_ips_using and self.proxy_ip_access_num <= 2:
if self.proxy_ip_use_num < len(self.proxy_ips_using):
print(self.proxy_ips_using)
print(self.proxy_ip_use_num)
ip = self.proxy_ips_using[self.proxy_ip_use_num]
self.proxy_ip_access_num += 1
request.meta['proxy'] = 'http://' + ip
return
else:
self.proxy_ip_access_num = 0
if not self.proxy_ips_using or self.proxy_ip_use_num >= len(self.proxy_ips_using):
self.get_proxy_ip()
self.proxy_ip_use_num = 0
ip = self.proxy_ips_using[self.proxy_ip_use_num]
self.proxy_ip_use_num += 1
if ip not in self.proxy_ips_used:
print("当前使用IP是:" + ip)
request.meta['proxy'] = 'http://'+ip
代理问题配置问题
这个问题有点莫名其妙。在测试scrapy脚本时,换了几家代理公司的api,第一次是可以正常运行的,但是第二次即换了一家后配置api后始终返回400,即代理的ip无法有效请求目标。最终调试发现,需要在代理中间件加个request.headers['Proxy-Authorization'] = basic_auth_header('name', 'passwd')
这条代码。。 就很坑,因为时而需要时而不需要。。
class HeaderMiddleware(object):
# 初始化
def __init__(self):
self.ua = UserAgent()
self.ip_num = 3
# 请求处理
def process_request(self, request, spider):
request.headers.setdefault("User-Agent", self.ua.random)
# 代理服务器
proxyHost = "dyn.horocn.com"
proxyPort = "50000"
# 代理隧道验证信息
proxyUser = "user"
proxyPass = "name"
proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
"host": proxyHost,
"port": proxyPort,
"user": proxyUser,
"pass": proxyPass
}
print("当前使用IP是:" + proxyMeta)
# import requests
# requests.get(url="http://124.223.76.169/test", proxies={'http': proxyMeta})
request.meta['proxy'] = proxyMeta
request.headers['Proxy-Authorization'] = basic_auth_header('GWGG8', 'oan7em')
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)