一个scrapy框架的爬虫(爬取京东图书)
我们的这个爬虫设计来爬取京东图书(jd.com)。
scrapy框架相信大家比较了解了。里面有很多复杂的机制,超出本文的范围。
1、爬虫spider
tips:
1、xpath的语法比较坑,但是你可以在chrome上装一个xpath helper,轻松帮你搞定xpath正则表达式
2、动态内容,比如价格等是不能爬取到的
3、如本代码中,评论爬取部分代码涉及xpath对象的链式调用,可以参考
# -*- coding: utf-8 -*- # import scrapy # 可以用这句代替下面三句,但不推荐
from scrapy.spiders import Spider
from scrapy.selector import Selector
from scrapy import Request
from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor from jdbook.items import JDBookItem # 如果报错是pyCharm对目录理解错误的原因,不影响 class JDBookSpider(Spider):
name = "jdbook"
allowed_domains = ["jd.com"] # 允许爬取的域名,非此域名的网页不会爬取
start_urls = [
# 起始url,这里设置为从最大tid开始,向0的方向迭代
"http://item.jd.com/11678007.html"
] # 用来保持登录状态,可把chrome上拷贝下来的字符串形式cookie转化成字典形式,粘贴到此处
cookies = {} # 发送给服务器的http头信息,有的网站需要伪装出浏览器头进行爬取,有的则不需要
headers = {
# 'Connection': 'keep - alive',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
} # 对请求的返回进行处理的配置
meta = {
'dont_redirect': True, # 禁止网页重定向
'handle_httpstatus_list': [301, 302] # 对哪些异常返回进行处理
} def get_next_url(self, old_url):
'''
description: 返回下次迭代的url
:param oldUrl: 上一个爬去过的url
:return: 下次要爬取的url
'''
# 传入的url格式:http://www.heartsong.top/forum.php?mod=viewthread&tid=34
list = old_url.split('/') #用等号分割字符串
old_item_id = int(list[3].split('.')[0])
new_item_id = old_item_id - 1
if new_item_id == 0: # 如果tid迭代到0了,说明网站爬完,爬虫可以结束了
return
new_url = '/'.join([list[0], list[1], list[2], str(new_item_id)+ '.html']) # 构造出新的url
return str(new_url) # 返回新的url def start_requests(self):
"""
这是一个重载函数,它的作用是发出第一个Request请求
:return:
"""
# 带着headers、cookies去请求self.start_urls[0],返回的response会被送到
# 回调函数parse中
yield Request(self.start_urls[0], callback=self.parse, headers=self.headers, cookies=self.cookies, meta=self.meta) def parse(self, response):
"""
用以处理主题贴的首页
:param response:
:return:
"""
selector = Selector(response)
item = JDBookItem()
extractor = LxmlLinkExtractor(allow=r'http://item.jd.com/\d.*html')
link = extractor.extract_links(response)
try:
item['_id'] = response.url.split('/')[3].split('.')[0]
item['url'] = response.url
item['title'] = selector.xpath('/html/head/title/text()').extract()[0]
item['keywords'] = selector.xpath('/html/head/meta[2]/@content').extract()[0]
item['description'] = selector.xpath('/html/head/meta[3]/@content').extract()[0]
item['img'] = 'http:' + selector.xpath('//*[@id="spec-n1"]/img/@src').extract()[0]
item['channel'] = selector.xpath('//*[@id="root-nav"]/div/div/strong/a/text()').extract()[0]
item['tag'] = selector.xpath('//*[@id="root-nav"]/div/div/span[1]/a[1]/text()').extract()[0]
item['sub_tag'] = selector.xpath('//*[@id="root-nav"]/div/div/span[1]/a[2]/text()').extract()[0]
item['value'] = selector.xpath('//*[@id="root-nav"]/div/div/span[1]/a[2]/text()').extract()[0]
comments = list()
node_comments = selector.xpath('//*[@id="hidcomment"]/div')
for node_comment in node_comments:
comment = dict()
node_comment_attrs = node_comment.xpath('.//div[contains(@class, "i-item")]')
for attr in node_comment_attrs:
url = attr.xpath('.//div/strong/a/@href').extract()[0]
comment['url'] = 'http:' + url
content = attr.xpath('.//div/strong/a/text()').extract()[0]
comment['content'] = content
time = attr.xpath('.//div/span[2]/text()').extract()[0]
comment['time'] = time
comments.append(comment)
item['comments'] = comments
except Exception, ex:
print 'something wrong', str(ex)
print 'success, go for next'
yield item next_url = self.get_next_url(response.url) # response.url就是原请求的url
if next_url != None: # 如果返回了新的url
yield Request(next_url, callback=self.parse, headers=self.headers, cookies=self.cookies, meta=self.meta)
2、存储管道:pipelines
tips:
1、本pipelines将爬取的数据存入mongo,比写本地文件靠谱,特别是多实例或者分布式情况。
# -*- coding: utf-8 -*- import pymongo
from datetime import datetime
from scrapy.exceptions import DropItem class JDBookPipeline(object):
def __init__(self, mongo_uri, mongo_db, mongo_coll):
self.ids = set()
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
self.mongo_coll = mongo_coll @classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DB'),
mongo_coll=crawler.settings.get('MONGO_COLL')
) def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
# 数据库登录需要帐号密码的话
# self.client.admin.authenticate(settings['MINGO_USER'], settings['MONGO_PSW'])
self.db = self.client[self.mongo_db]
self.coll = self.db[self.mongo_coll] def close_spider(self, spider):
self.client.close() def process_item(self, item, spider):
if item['_id'] in self.ids:
raise DropItem("Duplicate item found: %s" % item)
if item['channel'] != u'图书':
raise Exception('not book')
else:
#self.coll.insert(dict(item))
# 如果你不想锁死collection名称的话
self.ids.add(item['_id'])
collection_name = item.__class__.__name__ + '_' + str(datetime.now().date()).replace('-', '')
self.db[collection_name].insert(dict(item))
return item
3、数据结构:items
tips:
1、看到scrapy的item就笑了,这不是django么
# -*- coding: utf-8 -*- import scrapy class JDBookItem(scrapy.Item):
_id = scrapy.Field()
title = scrapy.Field()
url = scrapy.Field()
keywords = scrapy.Field()
description = scrapy.Field()
img = scrapy.Field()
channel = scrapy.Field()
tag = scrapy.Field()
sub_tag = scrapy.Field()
value = scrapy.Field()
comments = scrapy.Field()
4、scrapyd部署
很多朋友想做分布式爬虫,比如通过celery任务调起scarpy爬虫任务。
但是很不幸,scrapy想实现这样的方式并不简单。一个比较好的办法是用scrapyd管理爬虫任务。
你需要保证你的python环境安装了3个东西。
source kangaroo.env/bin/activate
pip install scrapy scrapyd scrapyd-client
在你的spider路径下启动scrapyd守护进程。
scrapyd
下面注册你的spider,先写配置文件scrapy.cfg
# Automatically created by: scrapy startproject
#
# For more information about the [deploy] section see:
# https://scrapyd.readthedocs.org/en/latest/deploy.html [settings]
default = jdbook.settings [deploy:jdbook]
url = http://localhost:6800/
project = jdbook
开始注册
#注册spider
scrapyd-deploy -p jdbook -d jdbook
#列出已注册的spider
scrapyd-deploy -l
输出:jdbook http://localhost:6800/
这样就已经注册好了
开始/停止爬虫:
curl -XPOST http://10.94.99.55:6800/schedule.json? -d project=jdbook -d spider=jdbook
输出:{"status": "ok", "jobid": "9d50b3dcabfc11e69aa3525400128d39", "node_name": "kvm33093.sg"}
curl -XPOST http://10.94.99.55:6800/cancel.json? -d project=jdbook -d job=9d50b3dcabfc11e69aa3525400128d39
输出:{"status": "ok", "prevstate": "running", "node_name": "kvm33093.sg"}
至此,你可以在celery任务中调用爬虫了,只需要发送如上url就可以。
而各个爬虫可以存放在不同的机器上,实现分布式爬取。
一个scrapy框架的爬虫(爬取京东图书)的更多相关文章
- 基于scrapy框架输入关键字爬取有关贴吧帖子
		基于scrapy框架输入关键字爬取有关贴吧帖子 站点分析 首先进入一个贴吧,要想达到输入关键词爬取爬取指定贴吧,必然需要利用搜索引擎 点进看到有四种搜索方式,分别试一次,观察url变化 我们得知: 搜 ... 
- python爬虫爬取京东、淘宝、苏宁上华为P20购买评论
		爬虫爬取京东.淘宝.苏宁上华为P20购买评论 1.使用软件 Anaconda3 2.代码截图 三个网站代码大同小异,因此只展示一个 3.结果(部分) 京东 淘宝 苏宁 4.分析 这三个网站上的评论数据 ... 
- 一个简单的python爬虫,爬取知乎
		一个简单的python爬虫,爬取知乎 主要实现 爬取一个收藏夹 里 所有问题答案下的 图片 文字信息暂未收录,可自行实现,比图片更简单 具体代码里有详细注释,请自行阅读 项目源码: # -*- cod ... 
- python制作爬虫爬取京东商品评论教程
		作者:蓝鲸 类型:转载 本文是继前2篇Python爬虫系列文章的后续篇,给大家介绍的是如何使用Python爬取京东商品评论信息的方法,并根据数据绘制成各种统计图表,非常的细致,有需要的小伙伴可以参考下 ... 
- Python爬虫-爬取京东商品信息-按给定关键词
		目的:按给定关键词爬取京东商品信息,并保存至mongodb. 字段:title.url.store.store_url.item_id.price.comments_count.comments 工具 ... 
- scrapy框架综合运用  爬取天气预报  + 定时任务
		爬取目标网站: http://www.weather.com.cn/ 具体区域天气地址: http://www.weather.com.cn/weather1d/101280601.shtm(深圳) ... 
- Scrapy 框架 使用 selenium 爬取动态加载内容
		使用 selenium 爬取动态加载内容 开启中间件 DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMidd ... 
- Scrapy框架——使用CrawlSpider爬取数据
		引言 本篇介绍Crawlspider,相比于Spider,Crawlspider更适用于批量爬取网页 Crawlspider Crawlspider适用于对网站爬取批量网页,相对比Spider类,Cr ... 
- Python 爬虫-爬取京东手机页面的图片
		具体代码如下: __author__ = 'Fred Zhao' import requests from bs4 import BeautifulSoup import os from urllib ... 
随机推荐
- AFN和SDWebImage请求网络图片的一点问题
			问题1.AFN 处理有关图片相关的请求的问题 在使用AFN Post网络图片的时候发现NSLocalizedDescription=Request failed: unacceptable conte ... 
- 为什么可以通过URL来调起APP - URL Scheme和Intent
			在手机浏览器中可以通过URL调起APP是不是很神奇?这篇文章就告诉你为什么. URL Scheme 先从前端能接触到的URL Scheme分析一下 丢wiki:https://en.wikipedia ... 
- 五,ESP8266 TCP服务器多连接
			一些时间去准备朋友的元器件了... 接着写,,争取今天写完所有的文章,,因为答应了朋友下周5之前要做好朋友的东西 对于TCP大家在玩AT指令的时候有没有发现客户端最多连接5个,,,再连接就不行了?? ... 
- 团队作业8----第二次项目冲刺(Beta阶段) 第四天
			BETA阶段冲刺第四天 1.小会议ing 2.每个人的工作 (1)昨天已完成的工作 1.修改了学生上传的方式: 2.完善了学生和老师修改的代码: (2) 今天计划完成的工作 (3) 工作中遇到的困难: ... 
- 201521123061 《Java程序设计》第十周学习总结
			201521123061 <Java程序设计>第十周学习总结 1. 本周学习总结 1.这周异常方面的知识主要是关于自定义异常,自定义的异常可以继承自Throwable或Exception类 ... 
- 201521123113《Java程序设计》第8周学习总结
			1. 本周学习总结 2. 书面作业 本次作业题集集合 Q1.List中指定元素的删除(题目4-1) 1.1 实验总结 remove函数中,开始我的写法是 for(int i=0;i<list.s ... 
- list,set,map总结
			学习了集合,脑子里list,set,map之间的关系有混乱,在这里整理一下.有兴趣的朋友可以看下. 先看下 list,set,map各自的特点 
- Java课程设计  学生基本信息管理系统    团队博客
			学生基本信息管理系统团队博客 项目git地址 https://git.oschina.net/Java_goddess/kechengsheji 项目git提交记录截图 项目功能架构图与主要功能流程图 ... 
- 初试 Vue.js
			1.为什么我会想要来弄弄vue这个前端框架呢? 答:前段时间被小程序刷屏了,然后就去弄了一下小程序,嗯挺简单的:头脑一发热后就想到vue2也发布一段时间了,何不也来尝尝vue2.0的味道,最后发现它们 ... 
- Oracle-表被锁住
			1.如果update 某个表,没有报错,等待很久都没结束,那很有可能是表被锁了. 2.查看被锁的对象 select sid,serial#,username,SCHEMANAME,osuser,MAC ... 
