标签。回到代码部分,对之前定义的movies做迭代,逐项获取要抓取的数据。
for movie in movies:
item['ranking'] = movie.xpath(
'.//div[@class="pic"]/em/text()').extract()[0]
item['movie_name'] = movie.xpath(
'.//div[@class="hd"]/a/span[1]/text()').extract()[0]
item['score'] = movie.xpath(
'.//div[@class="star"]/span[@class="rating_num"]/text()'
).extract()[0]
item['score_num'] = movie.xpath(
'.//div[@class="star"]/span/text()').re(r'(\d+)人评价')[0]
yield item
4.Url跳转(翻页)
如果到此为止,我们可以将https://movie.douban.com/top250页面中的第一页内容爬取到,但只有25项记录,要爬取全部的250条记录,就要执行下面代码:
next_url = response.xpath('//span[@class="next"]/a/@href').extract()
if next_url:
next_url = 'https://movie.douban.com/top250' + next_url[0]
yield Request(next_url)
首先通过xpath解析了页面中后页的链接,并赋值给next_url变量,如果我们当前在第一页,那么解析后页的链接就是?start=25&filter=。将解析的后页链接与完整url连接形成完整的地址,再次执行Request(),就实现了对全部250条记录的爬取。注意:通过xpath解析出的结果是列表,所以在引用的时候写成next_url[0]。
处理随机Head属性(随机User-Agent)
实现随机的head属性发送。主要改两个文件:
settings.py
USER_AGENT_LIST = [
'zspider/0.9-dev http://feedback.redkolibri.com/',
'Xaldon_WebSpider/2.0.b1',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)',
'Mozilla/5.0 (compatible; Speedy Spider; http://www.entireweb.com/about/search_tech/speedy_spider/)',
'Speedy Spider (Entireweb; Beta/1.3; http://www.entireweb.com/about/search_tech/speedyspider/)',
'Speedy Spider (Entireweb; Beta/1.2; http://www.entireweb.com/about/search_tech/speedyspider/)',
'Speedy Spider (Entireweb; Beta/1.1; http://www.entireweb.com/about/search_tech/speedyspider/)',
'Speedy Spider (Entireweb; Beta/1.0; http://www.entireweb.com/about/search_tech/speedyspider/)',
'Speedy Spider (Beta/1.0; www.entireweb.com)',
'Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)',
'Speedy Spider (http://www.entireweb.com/about/search_tech/speedyspider/)',
'Speedy Spider (http://www.entireweb.com)',
'Sosospider+(+http://help.soso.com/webspider.htm)',
'sogou spider',
'Nusearch Spider (www.nusearch.com)',
'nuSearch Spider (compatible; MSIE 4.01; Windows NT)',
'lmspider (lmspider@scansoft.com)',
'lmspider lmspider@scansoft.com',
'ldspider (http://code.google.com/p/ldspider/wiki/Robots)',
'iaskspider/2.0(+http://iask.com/help/help_index.html)',
'iaskspider',
'hl_ftien_spider_v1.1',
'hl_ftien_spider',
'FyberSpider (+http://www.fybersearch.com/fyberspider.php)',
'FyberSpider',
'everyfeed-spider/2.0 (http://www.everyfeed.com)',
'envolk[ITS]spider/1.6 (+http://www.envolk.com/envolkspider.html)',
'envolk[ITS]spider/1.6 ( http://www.envolk.com/envolkspider.html)',
'Baiduspider+(+http://www.baidu.com/search/spider_jp.html)',
'Baiduspider+(+http://www.baidu.com/search/spider.htm)',
'BaiDuSpider',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0) AddSugarSpiderBot www.idealobserver.com',
]
DOWNLOADER_MIDDLEWARES = {
'spider_douban.middlewares.RandomUserAgentMiddleware': 400,
'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
}
USER_AGENT_LIST定义了一些浏览器user-agent属性,网上有很多,可以找来直接加进去,需要注意的是有些user-agent信息是移动设备(手机或平板)的,如果不注意的话,可能请求到的数据与你看到的数据有较大差异;
DOWNLOADER_MIDDLEWARES定义了下载器中间件,它在发送页面请求数据的时候被调用。
middlewares.py
from spider_douban.settings import USER_AGENT_LIST
import random
class RandomUserAgentMiddleware():
def process_request(self, request, spider):
ua = random.choice(USER_AGENT_LIST)
if ua:
request.headers.setdefault('User-Agent', ua)
在RandomUserAgentMiddleware()中,每次发送请求数据,会在USER_AGENT_LIST中随机选择一条User-Agent记录。
结果保存
编辑pipelines.py文件:
from scrapy import signals
from scrapy.contrib.exporter import CsvItemExporter
class SpiderDoubanPipeline(CsvItemExporter):
def __init__(self):
self.files = {}
@classmethod
def from_crawler(cls, crawler):
print('==========pipeline==========from_crawler==========')
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def spider_opened(self, spider):
savefile = open('douban_top250_export.csv', 'wb+')
self.files[spider] = savefile
print('==========pipeline==========spider_opened==========')
self.exporter = CsvItemExporter(savefile)
self.exporter.start_exporting()
def spider_closed(self, spider):
print('==========pipeline==========spider_closed==========')
self.exporter.finish_exporting()
savefile = self.files.pop(spider)
savefile.close()
def process_item(self, item, spider):
print('==========pipeline==========process_item==========')
print(type(item))
self.exporter.export_item(item)
return item
SpiderDoubanPipeline类是建立项目的时候自行建立的,为了保存文件,做了修改。
def from_crawler(cls, crawler):
在此方法中,定义了一个数据收集器(cls)的实例:‘pipeline’。
signals:Scrapy使用信号来通知事情发生。您可以在您的Scrapy项目中捕捉一些信号(使用 extension)来完成额外的工作或添加额外的功能,扩展Scrapy。虽然信号提供了一些参数,不过处理函数不用接收所有的参数 - 信号分发机制(singal dispatching mechanism)仅仅提供处理器(handler)接受的参数。您可以通过 信号(Signals) API 来连接(或发送您自己的)信号。
connect:链接一个接收器函数(receiver function) 到一个信号(signal)。signal可以是任何对象,虽然Scrapy提供了一些预先定义好的信号。
def spider_opened(self, spider):
CsvItemExporter(savefile):输出 csv 文件格式. 如果添加 fields_to_export 属性, 它会按顺序定义CSV的列名.
def spider_closed(self, spider):
def process_item(self, item, spider):
启用pipeline
为了让我们定义的pipeline生效,要在settings.py文件中,打开ITEM_PIPELINES注释:
ITEM_PIPELINES = {
'spider_douban.pipelines.SpiderDoubanPipeline': 300,
}
执行爬虫
scrapy crawl douban_movie_top250
执行爬虫能够看到爬取到的数据。。。
如果之前pipeline部分代码没有写,也可以用下面的命令,在爬虫执行的时候直接导出数据:
scrapy crawl douban_movie_top250 -o douban.csv
增加-o参数,可以将爬取到的数据保存到douban.csv文件中。。
文件编码的问题
我在linux服务器执行爬虫,生成csv文件后,在win7系统中用excel打开变成乱码。在网上找了一些文章,有的文章直接改变linux文件默认编码,但是感觉这么做会对其他项目产生影响。最后选择一个相对简单的方式。按这几步执行就可以:
不要直接用excel打开csv文件。先打开excel,建立空白工作表。
-
选择数据选项卡,打开获取外部数据中的自文本。
在导入文本文件对话框中选择要导入的csv文件。
在文本导入向导 - 第1步中,设置文件原始格式为65001 : Unicode (UTF-8)
继续下一步选择逗号分隔,就可以导入正常文本了。
作者:Jero 来源:https://segmentfault.com/a/1190000013268442
学习Python和网络爬虫关注公众号:datanami

近期文章:
Python之多线程爬虫抓取网页图片
一篇文章搞懂的Python的中最难的概念
用Python的代码自动抢火车票
用python代码实现微信撤消消息查看| Python itchat