Python集成scrapy和selenium爬取苏宁图书
环境:python3.6 pycharm2018.1.3
前言
本人渣渣一枚,为爬虫苏宁图书获取数据,将获得的数据保存在MangoDB中,现在一步步地把步骤写出来。
步骤–分析苏宁图书
- 因为我是想直接拿取图书列表页的信息,所以这里就不从首页开始分析。首先先打开列表页,我发现列表页有60条数据,但是我点击查看网页源代码中只有30条数据,后面使用network调试工具,发现列表页后面30条的数据是通过用户拉取列表页下滑框时,它会发起ajax请求,然后才会获取后面的30条数据。
这个请求就是我在下拉框我拉到下面时网页发起的ajax请求,我点击Response查看数据发现了后面的30条数据。 - 使用scrapy框架创建一个爬取苏宁图书的项目
这样就可以开始爬取数据了scrapy startproject suning # 创建爬虫项目 # 创建好之后,进入这个项目中 scrapy genspider book suning.com # 生成一个爬虫文件
- 在管道中pipeline做好准备工作
from selenium import webdriver from pymongo import MongoClient class SuningPipeline(object): def __init__(self): """定义MongoDB对象,保存数据""" # 创建连接对象 conn = MongoClient() # 创建数据库以及要保存到的集合 self.home = conn["suning"]["book"] def open_spider(self,spider): """开启爬虫""" # 创建一个selenium的chrom浏览器对象 spider.driver = webdriver.Chrome() def process_item(self, item, spider): # 当数据解析完后会返回到这里,使用创建的MongoDB对象保存数据 self.home.insert(item) return item def close_spider(self,spider): """爬虫处理完数剧关闭爬虫""" spider.driver.quit()
- 在middlewares中自定义下载器中间件
import time from scrapy import signals from scrapy.http import TextResponse class SeleniumMid(object): def process_request(self,request,spider): # 使用在管道中开启爬虫open_spider方法中定义的selenium对象请求url # 做到集成爬取数据 # 因为每次请求都会去请求robots协议,这里判断如果是请求robots,不在selenium中做 if spider.name == "book" and request.meta.get("is_selenium"): spider.driver.get(request.url) # selenium调用js的方法,里面传入的是执行的js代码 spider.driver.execute_script("window.scrollTo(0,10000)") time.sleep(3) spider.driver.execute_script("window.scrollTo(0,10000)") time.sleep(3) # 这里得到的内容是element中的内容,包含js和css请求后的所有内容 content = spider.driver.page_source return TextResponse(url=spider.driver.current_url,body=content.encode(),request=request)
- 最后修改自己创建的爬虫程序文件代码
import scrapy
class BookSpider(scrapy.Spider):
name = 'book'
allowed_domains = ['book.suning.com']
start_urls = ['https://list.suning.com/1-502687-0.html']
def start_requests(self):
# 调用start_url的地方
for url in self.start_urls:
yield scrapy.Request(url, dont_filter=True, meta={"is_selenium": True})
def parse(self, response):
li_list = response.xpath("//li[contains(@class,'product ')]")
print(len(li_list))
for li in li_list:
item = {}
# 书的名字
item["book_name"] = li.xpath(".//p[@class='sell-point']/a/text()").extract_first().strip()
# 书的价格
item["book_price"] = li.xpath(".//em[@class='prive price ']//text()").extract()
# 将爬取完后的数据交给管道去解析并保存
return item
最后在settings设置文件中将中间件和管道打开就可以运行了,其实最后我爬取数据时,只爬了两个数据,如果有想爬别的数据的话,大概格式就跟这个一样。