
爬蚂蜂窝,然后遇到了 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 不就好了吗 |