Scrapy框架之带有分页的详情页面抓取
2017-09-26 本文已影响187人
HideOnStream
最近在动手搭建一个爬虫框架,在考虑到设计上的一些细节的时候遇到一些问题,比如,对于详情页面带有多页的如何恰当的实现?于是乎想参考Scrapy爬虫框架对于这个场景的实现,网上谷歌,有人给出思路,但是没有完整的实现,所以在这里呈现一个完整的例子。
假设我想采集某新闻网站数据,比如说news.7654.com,为了增加网站的pv,uv量,很多文章都这样,如http://news.7654.com/a/2184936178569937140_1?TAG=3_27,带有多个分页。如下图:
多页.png
采集一篇文章肯定不能只抓取它的第一页数据,那样是不完整的,那么该如何抓取全部的页面呢?大致思路是,在抓取到第一页的时候提取出需要的数据信息,然后查看是否还有下一页,如果有下一页,则提取出下一个页面的链接,生成一个Request对象,并且将刚才提取出来的有效信息作为meta参数传给这个Request对象,然后将这个Request对象交给Scrapy引擎,如果没有下一页,就将这些meta里面的信息整合起来,生成Item即可。
好了,看代码:
import re
import scrapy
from lxml import html
from lxml.html import clean
from urllib.parse import urljoin
from newsproject.items import NewsprojectItem
class NewsSpider(scrapy.Spider):
name = 'news_spider'
allowed_domains = ['news.7654.com']
start_urls = ['http://news.7654.com/a/2184936178569937140_1?TAG=3_27']
def parse(self, response):
# 调用clean类,用于去掉非html标准标签,以及scripts脚本等。
cleaner = clean.Cleaner()
tree = html.fromstring(cleaner.clean_html(response.body.decode()))
# 获得下一页的链接
next_url = tree.xpath("//div[@class='detailaddnum pb15']/a[last()]/@href")
# 获得当前页面新闻的全部文本
article_tag = tree.xpath("//div[@class='detail_pagination']")[0]
article_content = article_tag.xpath('string(//*)').strip(" ").replace("\n", "").replace("\r", "")
# 如果有下一页链接
if next_url and re.match(r'http://news.7654.com/a/[0-9]+_[0-9]+\?TAG=3_27', next_url[0]):
if not response.meta.get('article_content'):
response.meta.update({'article_content': [article_content]})
else:
response.meta['article_content'].append(article_content)
yield scrapy.Request(urljoin(response.request.url, next_url[0]),
meta=response.meta, callback=self.parse)
else:
article_detail = ""
for content in response.meta['article_content']:
article_detail += content
item = NewsprojectItem()
# 当前页面的有效信息也要整合到一起
item['article_detail'] = article_detail + article_content
yield item
注意:在找最后一页的时候一定要做正则校验,因为新闻类网站很喜欢在最后一页放一个广告类页面,这个网站还好,只是在最后一页给你推荐的是另一篇新闻;提取出的下一页链接可能是一个相对地址。
好了,如何利用Scrapy抓取详情页带分页的介绍就到这里,在最后抛出一个新的问题,新闻里面都喜欢带图片,那么如何在抓取文章的时候同时把图片也抓取?(关键不是抓取,是如何把图片和文章整合)