爬蚂蜂窝,然后遇到了 521response 反爬。自己搜了一下这个反爬还好处理,就是解码设置 cookie 的事。 但是我后来测试时候发现其实只要设置一个 5 秒左右的延时,通过 selenium 返回的 page_source 就是跳过反爬信息得到的完整页面信息了。
于是综上探索,我预想的是在 scrapy 中间件中加入 selenium,在 process_request 里做 get 请求之后,time.sleep 四五秒钟,然后返回 response 做后续处理。
想的是很美好,但是测试时候发现,因为中间件的 selenium 做 get 请求时,url 地址是 request.url,而这个 url 好像因为之前 scrapy 自带的 request 没有通过反爬然后就从一开始 url 就变成了 www.mafengwo.cn/robot.txt ,那这个 url 肯定是没法用了。用 spider.start_urls 的话又要处理一个列表问题,如果是爬好几个页面感觉从这个列表提取 url 也不是很靠谱啊。
那么有什么靠谱点的办法,让 request.url 传递过去正常的 url 呢?
附上 selenium 中间件的代码:
class SeleniumMiddleWares(object):
def __init__(self):
self.driver_path = '/Users/michealki/Downloads/chromedriver'
self.options = Options()
self.options.add_experimental_option('excludeSwitches', ['enable-automation'])
# self.options.add_argument('--headless')
self.driver = selenium.webdriver.Chrome(executable_path=self.driver_path,options=self.options)
@classmethod
def from_crawler(cls, crawler):
s = cls()
crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)
return s
def process_request(self, request, spider):
#url = request.url
url = spider.start_urls[0]
self.driver.get(url)
time.sleep(5)
return HtmlResponse(url=self.driver.current_url, body=self.driver.page_source,
encoding="utf-8", request=request)
def spider_closed(self, spider):
self.driver.quit()
class Spider0(scrapy.Spider):
name = 'spider0'
start_urls = ['http://www.mafengwo.cn/poi/7918553.html']
def parse(self,response):
pass
1
wqzjk393 OP 另外求教一下。。。md 下面怎么正常换行呢?直接回车的话实际显示出来总是发现回车没有效果,中间空一行的话又感觉格式好丑
|
3
locoz 2019-11-22 00:31:07 +08:00
“而这个 url 好像因为之前 scrapy 自带的 request 没有通过反爬然后就从一开始 url 就变成 www.mafengwo.cn/robot.txt”这个描述,看起来应该是你没关闭 scrapy 的 robots 文件检测导致的?
|
4
locoz 2019-11-22 00:31:51 +08:00
“用 spider.start_urls 的话又要处理一个列表问题,如果是爬好几个页面感觉从这个列表提取 url 也不是很靠谱啊。”
看不出哪里不靠谱,什么叫“又要处理一个列表问题”? |
5
dreamerlv3ex 2019-11-22 09:16:38 +08:00
scrapy 担心你进去,帮你画了一条线,看你要不要越过吧..你要越过去就去设置配置就行..
|
6
wqzjk393 OP @locoz
@dreamerlv3ex 原来可以直接越过 robot 检测啊。。。我还以为这个是网站检测到爬虫程序然后强制把 response 从页面跳到了 robot 这里,那看起来应该是 scrapy 主动去 robot 里检测是否在人家准许爬取的范围内了。嗯 robot 这方面了解的还是太少了,多谢指教~ |
7
wqzjk393 OP @locoz 简单说就是,start_urls 是一个列表,如果我引入中间件并在中间件通过 start_urls 访问里面的某个 url,需要一个 index 来索引这个列表啊,这个 index 怎么传过去呢?如果就是一个页面那我直接 start_urls[0]就行,但是多个页面的话我不知道有没有哪个参数能表明当前爬取的 start_urls 是第几个
|
8
skinny 2019-11-22 10:18:12 +08:00
settings.py 里关闭 ROBOT.TXT 检测,更换 UA ;并不是强制必须从 start_urls 开始,可以重写 start_requests 方法,yield 请求,parse callback 里也可以 yield 请求。
话说我觉得 scrapy 太难用了,需求多一点就要改很多东西,精确数据爬取还是自己写的灵活。 |
9
locoz 2019-11-22 10:57:19 +08:00
|
10
GPU 2019-11-22 11:25:37 +08:00
scrapy-splash 这个东西了解一下?
之前我搞爬虫的时候也是找到 selenium, 但是配置太麻烦最后用了前者很简单。 这个东西好似好似是 scrapy 开源出来的 |
11
wqzjk393 OP @locoz 嗯。。试了一下,scrapy 会先产生一个 robot 的 request 然后再产生一个真正 url 的 request。就是因为首先产生了 robot 请求,然后我中间件没有判断 url 是不是 xxx/robot.txt 就直接拿去做自定义 request_process 了,那第二次真正的 url 请求自然就不会传到中间件了。用 request.url 是没问题的。
|
12
wqzjk393 OP |
13
GPU 2019-11-22 12:13:13 +08:00
@wqzjk393 #12 scrpay-splash 完全可以替代 selenium,xpath 之类的功能是 scrapy 自带的把
|
14
warcraft1236 2019-11-22 13:43:25 +08:00
@GPU splash 渲染出来的页面和浏览器渲染出来的还是有差别。之前有个网站把视频的地址换成了加密字符串,需要执行一段 js 来解密,我发现用 splash 并不能正常的解密出来地址
|
15
RicardoY 2019-11-22 13:59:13 +08:00 via Android
你不应该在 middleware 里直接处理 start_urls 这个列表 ..直接处理 request 不就好了吗
|