Python下用Scrapy和MongoDB构建爬虫系统(2),scrapymongodb,未经许可,禁止转载!英文
Python下用Scrapy和MongoDB构建爬虫系统(2),scrapymongodb,未经许可,禁止转载!英文
本文由 编橙之家 - PyPer 翻译,笑虎 校稿。未经许可,禁止转载!英文出处:realpython。欢迎加入翻译组。
在上一篇中,我们实现了一个基本网络爬虫,它可以从StackOverflow上下载最新的问题,并将它们存储在MongoDB数据库中。在本文中,我们将对其扩展,使它能够爬取每个网页底部的分页链接,并从每一页中下载问题(包含问题标题和URL)。
在你开始任何爬取工作之前,检查目标网站的使用条款并遵守robots.txt文件。同时,做爬取练习时遵守道德,不要在短时间内向某个网站发起大量请求。像对待自己的网站一样对待任何你将爬取的网站。
开始
有两种可能的方法来接着从上次我们停下的地方继续进行。
第一个方法是,扩展我们现有的网络爬虫,通过利用一个xpath表达式从”parse_item”方法里的响应中提取每个下一页链接,并通过回调同一个parse_item方法产生一个请求对象。利用这种方法,爬虫会自动生成针对我们指定的链接的新请求,你可以在Scrapy文档这里找到更多有关该方法的信息。
另一个更简单的方法是,使用一个不同类型的爬虫—CrawlSpider(链接)。这是基本Spider的一个扩展版本,它刚好满足我们的要求。
CrawlSpider
我们将使用与上一篇教程中相同的爬虫项目,所以如果你需要的话可以从repo上获取这些代码。
创建样板
在“stack”目录中,首先由crawl模板生成爬虫样板。
Python$ scrapy genspider stack_crawler stackoverflow.com -t crawl Created spider 'stack_crawler' using template 'crawl' in module: stack.spiders.stack_crawler
Scrapy项目现在看起来应该像这样:
Python├── scrapy.cfg └── stack ├── __init__.py ├── items.py ├── pipelines.py ├── settings.py └── spiders ├── __init__.py ├── stack_crawler.py └── stack_spider.py
stack_crawler.py文件内容如下:
Python# -*- coding: utf-8 -*- import scrapy from scrapy.contrib.linkextractors import LinkExtractor from scrapy.contrib.spiders import CrawlSpider, Rule from stack.items import StackItem class StackCrawlerSpider(CrawlSpider): name = 'stack_crawler' allowed_domains = ['stackoverflow.com'] start_urls = ['http://www.stackoverflow.com/'] rules = ( Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True), ) def parse_item(self, response): i = StackItem() #i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract() #i['name'] = response.xpath('//div[@id="name"]').extract() #i['description'] = response.xpath('//div[@id="description"]').extract() return i
我们只需要对这个样板做一些更新。
更新“start_urls”列表
首先,添加问题的第一个页面链接到start_urls列表:
Pythonstart_urls = [ 'http://stackoverflow.com/questions?pagesize=50&sort=newest' ]
更新“rules”列表
接下来,我们需要添加一个正则表达式到“rules”属性中,以此告诉爬虫在哪里可以找到下一个页面链接:
Pythonrules = [ Rule(LinkExtractor(allow=r'questions?page=[0-9]&sort=newest'), callback='parse_item', follow=True) ]
现在爬虫能根据那些链接自动请求新的页面,并将响应传递给“parse_item”方法,以此来提取问题和对应的标题。
如果你仔细查看的话,可以发现这个正则表达式限制了它只能爬取前9个网页,因为在这个demo中,我们不想爬取所有的176234个网页。
更新“parse_item”方法
现在我们只需编写如何使用xpath解析网页,这一点我们已经在上一篇教程中实现过了,所以直接复制过来。
Pythondef parse_item(self, response): questions = response.xpath('//div[@class="summary"]/h3') for question in questions: item = StackItem() item['url'] = question.xpath( 'a[@class="question-hyperlink"]/@href').extract()[0] item['title'] = question.xpath( 'a[@class="question-hyperlink"]/text()').extract()[0] yield item
这就是为爬虫提供的解析代码,但是现在先不要启动它。
添加一个下载延迟
我们需要通过在settings.py文件中设定一个下载延迟来善待StackOverflow(和任何其他网站)。
PythonDOWNLOAD_DELAY = 5
这告诉爬虫需要在每两个发出的新请求之间等待5秒钟。你也很有必要做这样的限制,因为如果你不这么做的话,StackOverflow将会限制你的访问流量,如果你继续不加限制地爬取该网站,那么你的IP将会被禁止。所有,友好点—要像对待自己的网站一样对待任何你爬取的网站。
现在只剩下一件事要考虑—存储数据。
MongoDB
上次我们仅仅下载了50个问题,但是因为这次我们要爬取更多的数据,所有我们希望避免向数据库中添加重复的问题。为了实现这一点,我们可以使用一个MongoDB的 upsert方法,它意味着如果一个问题已经存在数据库中,我们将更新它的标题;否则我们将新问题插入数据库中。
修改我们前面定义的MongoDBPipeline:
Pythonclass MongoDBPipeline(object): def __init__(self): connection = pymongo.Connection( settings['MONGODB_SERVER'], settings['MONGODB_PORT'] ) db = connection[settings['MONGODB_DB']] self.collection = db[settings['MONGODB_COLLECTION']] def process_item(self, item, spider): for data in item: if not data: raise DropItem("Missing data!") self.collection.update({'url': item['url']}, dict(item), upsert=True) log.msg("Question added to MongoDB database!", level=log.DEBUG, spider=spider) return item
为简单起见,我们没有优化查询,也没有处理索引值,因为这不是一个生产环境。
测试
启动爬虫!
Python$ scrapy crawl questions
现在你可以坐下来,看着你的数据库渐渐充满数据。
结论
你可以从Github库下载整个源代码,也可以在下面评论或提问。
相关内容
- 使用 psutil 和 MongoDB 做系统监控,psutilmongodb,使用 Pyth
- Tornado+MongoDB 实现微信公众号自动回复,tornadomongodb, T
- Python下用Scrapy和MongoDB构建爬虫系统(1),scrapymongodb
- Python下用Scrapy和MongoDB构建爬虫系统(2),scrapymongodb
- python使用pymongo连接MongoDB,pymongomongodb,本文是一个Pyth
- Python+MongDB实现短链接,pythonmongdb实现,实现任意数制变
- python连接mongodb的基本代码,python连接mongodb,from pymongo
- pymongo中使用大于、小于、大于等于、小于等于的查询方
- python连接mongodb的基本代码,python连接mongodb,from pymongo
- 在pycharm上mongodb配置及可视化设置方法,pycharmmongodb
评论关闭