1、任务定义:
爬取某动态分页页面中所有子话题的内容。
所谓“动态分页”:是指通过javascript(简称“js”)点击实现翻页,很多时候翻页后的页面地址url并没有变化,而页面内容随翻页动作动态变化。
2、任务难点及处理方法:
难点:
1) scrapy如何动态加载所有“下一页”:要知道scrapy本身是不支持js操作的。
2) 如何确保页面内容加载完成后再进行爬取:由于内容是通过js加载的,如果不加控制,很可能出现爬到空页面的情况。
处理方法:
1)scrapy+selenium模拟浏览器点击:通过模拟浏览器点击的方式进行翻页,从而获取每一页内部的有效链接。
2)使用WebDriverWait()等待数据加载:即确保对应内容加载完成后,再进行相应爬取任务。
3、基本思路:
1) 通过模拟浏览器翻页(涉及模拟点击翻页问题),获取每个分页中待爬取页面的url(涉及数据加载问题),将url列表存入文件;
2) 针对每一个url进行普通的爬取。
4、待爬取页面分析:
举例:爬取某网站中所有子话题的内容。
1)子话题都在ul[@class="post-list"]标签下,xpath可以写成li[@class],表示所有具备class属性的li标签。
2)要想爬取所有页面,需要浏览器模拟点击右上角的“下一页”标签(<li>)。具体分析页面代码后发现,最后一页的“下一页”标签不可点击,可以作为停止获取url列表的标志。
最后一页的“下一页”标签:<liclass="pg_next pg_empty"data-reactid="XX"></li>
其余的“下一页”标签:<liclass="pg_next"data-reactid="XX"></li>
next_page = response.xpath('//ul[@class="pg1"]/li[@class="pg_next"]')
5、Spider代码:
# -*- coding: utf-8 -*- import scrapy import time import base64 from selenium import webdriver from selenium.webdriver.support.ui importWebDriverWait from buluo.items import BuluoItem
class buluoSpider(scrapy.Spider): name = 'buluo_spider' def __init__(self, bid = None): #示例:bid = 12339 """初始化起始页面和游戏bid """ super(buluoSpider, self).__init__() self.bid = bid #参数bid由此传入 self.start_urls = ['http://buluo.qq.com/p/barindex.html?bid=%s' % bid] self.allowed_domain = 'buluo.qq.com' self.driver = webdriver.Firefox() self.driver.set_page_load_timeout(5) #throw a TimeoutException when thepage load time is more than 5 seconds.
def parse(self, response): """模拟浏览器实现翻页,并解析每一个话题列表页的url_list """ url_set = set() #话题url的集合 self.driver.get(response.url) while True: wait = WebDriverWait(self.driver, 2) wait.until(lambda driver:driver.find_element_by_xpath('//ul[@class="post-list"]/li[@class]/a'))#VIP,内容加载完成后爬取 sel_list = self.driver.find_elements_by_xpath('//ul[@class="post-list"]/li[@class]/a') url_list = [sel.get_attribute("href") for sel in sel_list] url_set |= set(url_list) try: wait =WebDriverWait(self.driver, 2) wait.until(lambda driver:driver.find_element_by_xpath('//ul[@class="pg1"]/li[@class="pg_next"]'))#VIP,内容加载完成后爬取 next_page =self.driver.find_element_by_xpath('//ul[@class="pg1"]/li[@class="pg_next"]') next_page.click() #模拟点击下一页 except: print "#####Arrive thelast page.#####" break with open('url_set.txt', mode='w') as f: f.write(repr(url_set)) for url in url_set: yield scrapy.Request(url, callback=self.parse_content)
def parse_content(self, response): """提取话题页面内容,通过pipeline存入指定字段 """ item = BuluoItem() item['timestamp'] = time.strftime('%Y-%m-%d %H:%M:%S') item['bid'] = self.bid item['url'] = response.url #item['content'] = response.body.decode('utf-8') item['content'] = base64.b64encode(response.body) #编码为Base64的网页内容 yield item
6、爬虫运行:
其余还需配置好settings.py、items.py和pipeline.py等文件,cmd中运行如下命令,即可根据游戏编号爬取想要的子话题内容:
scrapy crawl buluo_spider -a bid=12339
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试