文章目录 思路1. 根据关键字构造豆瓣搜索url, 根据结果获取书的id2. 根据id, 构造该书评论的url链接3. 爬取网页内容, 并构造下一页url4. 重复步骤3, 反复爬取 过程1. 页面爬取测试2. 使用selenium工具获取id3. 将selenium集成到scrapy中4. 爬取结果5. 阶段性spider代码 ip异常问题1. 给selenium添加代理2. 给scrapy添加代理3. 注意
想做一个爬虫, 输入一个关键字, 然后爬取豆瓣读书的第一个搜索结果的所有评论.
思路 1. 根据关键字构造豆瓣搜索url, 根据结果获取书的id
如https://book.douban.com/subject_search?search_text=太空漫游, 第一个结果的链接中包含了这本书的id.
使用scrapy genspider doubanComments book.douban.com生成爬取模板
基本代码爬取豆瓣读书主页book.douban.com 成功
# -*- coding: utf-8 -*-import scrapyclass DoubancommentsSpider(scrapy.Spider): name = 'doubanComments' allowed_domains = ['book.douban.com'] start_urls = ['https://book.douban.com/'] def parse(self, response): print("hello?") with open("doubanComments.html", 'wb') as douban_comments_file: douban_comments_file.write(response.body)
爬取太空漫游评论页也成功
但是, 当我查看搜索页面的源码时, 发现并没有列表的信息, 关键字"太空漫游"少的可怜. 仔细查看发现, 它使用js渲染的, 直接看是看不到的.
用Chrome的检查元素发现, 可以看到列表信息. 但是直接爬取是看不到的. 因此无法用这种简单的方法找到书的id.
因此我们使用可以查看js渲染结果的工具Selenium.
首先安装Selenium
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
然后下载ChromeDriver
到官网下载对应系统和版本
写一个简单的selenium程序, 成功加载出js渲染的内容
代码
将selenium集成到scrapy中, 写他所在的getID函数用来获取一本书的id.
接下来就是普通的爬虫爬取过程了, 内容如
初始化csv文件, 因为后面的写入评论用的是追加模式, 每次运行都要重新将评论按行写入到csv文件中xpath选择器找出下一页的href, 构造下一页的链接使用scrapy.Request() 进行下一个页面的爬取 4. 爬取结果爬取了太空漫游的1700+的评论
九州的5000+的评论
但是遇到了爬取九州的评论时候遇到了一个问题. 同一个ip在短时间内大量访问豆瓣, 被发现了, 然后禁止我爬取了.
可以设置程序隔一段时间爬取一次, 也可以随机设置时间, 显得是人在操作. 不过这样爬完的时间就长了很多.
或者可以设置代理
免费的西刺代理
找一个可行的ip
需要注意的是, 免费代理ip需要测试多次找到一个可以使用的
1. 给selenium添加代理原先browser = webdriver.Chrome() 改成下面有代理选项的代码
proxy = '61.128.208.94:3128' # 免费的代理ip chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--proxy-server=http://' + proxy) browser = webdriver.Chrome(chrome_options=chrome_options) 2. 给scrapy添加代理首先在middlewares.py文件的最后面, 添加下面的代理类
class ProxyMiddleware(object): def process_request(self, request, spider): request.meta['proxy'] = "https://61.128.208.94:3128" # 改成自己的代理然后在settings.py后面添加下面代码
# 设置代理DOWNLOADER_MIDDLEWARES = { 'tutorial.middlewares.ProxyMiddleware': 100, # tutorial改成自己的项目名称}使用selenium代理时, 可以使用browser.get('http://httpbin.org/get')来查看代理是否生效
3. 注意上面的这个方法暂时只是权宜之计, 因为只设置了一个ip, 所以当这个新的ip对豆瓣进行访问时, 如果他在一定时间内的访问次数过多, 就也会封ip, 这这么短的时间内, 可能还来不及爬完一本书的全部评论. 所以正解应该是设置代理池(还不会).