本篇将谈一些scrapy的进阶内容,帮助大家能更熟悉这个框架。


1. 站点选取

现在的大网站基本除了pc端都会有移动端,所以需要先确定爬哪个。

比如爬新浪微博,有以下几个选择:

  1. www.weibo.com,主站
  2. www.weibo.cn,简化版
  3. m.weibo.cn,移动版

上面三个中,主站的微博数据是动态加载的,意味着光看源码是看不到数据的,想爬的话要么搞清楚其api访问情况,要么模拟js,那样的话花的力气可能就有点多了。weibo.cn是一个简化版,数据能直接从网页源代码中解析出来,但使用正则或xpath取网页中的元素仍然是无聊且费时的,更不用说偶尔的页面结构错误更让人抓狂。 相比之下,移动版的爬虫最好写,因为移动版能直接拿到json格式的数据。

一般来说,有移动版的网站优先爬移动版,会节省很多力气。


2. 模拟登录

现在需要登录才能正常浏览的网站的越来越多了,对爬虫也越来越不友好...所以模拟登录在不少场合都是必不可少的。

首先,最简单的模拟登录是只有用户名密码的登录。这时候只需要在发送第一个请求时加上登录表单数据即可:

def start_requests(self):
return scrapy.FormRequest(
formdata={'username': '***', 'password': '***'},
callback=self.after_login
)

如果不知道登录页面是哪一个的话,也可以在返回第一个请求后登录:

def parse(self, response):
return scrapy.FormRequest.from_response(
response,
formdata={'username': '***', 'password': '***'},
callback=self.after_login
)

为了保持登录,注意cookie是不能关闭的(默认情况是开着的,可以在settings.py中设置)。

如果需要验证码的话,网上有一些提取分析验证码图片的包,可以提取出来然后手动输入验证码。

上面只是一些简单的登录情况,如果验证码很变态(比如需要鼠标滑动)或者登录过程很复杂,需要各种加密(比如新浪微博pc端的登陆)的话,模拟登录确实是个很让人头大的问题。这时候有另一个通用办法,那就是cookie模拟登录。网站想知道我们的登录状态,都是通过cookie来确认的,所以我们只需要在每次request的时候都附带上cookie即可实现已登录的效果。

那么,如何获得cookie呢?有chrome的可以F12打开Network界面,这时候人工网页登录,即可在headers中看到cookie。得到cookie后,只需要在request中加入自己的cookie即可。

self.cookie = {"_T_WM": self.cookie_T_WM,
...
"SSOLoginState": self.cookie_SSOLoginState} return Request(url, cookies=self.cookie, callback=self.parse_page)

3. 网页解析

一般来说,使用xpath和css已经可以应付所有的html源码了,剩下的只是耐心加细心...要是有心的话也可以Item Loaders,方便后期的维护,下面摘自官方文档:

def parse(self, response):
l = ItemLoader(item=Product(), response=response)
l.add_xpath('name', '//div[@class="product_name"]')
l.add_xpath('name', '//div[@class="product_title"]')
l.add_xpath('price', '//p[@id="price"]')
l.add_css('stock', 'p#stock]')
l.add_value('last_updated', 'today')
return l.load_item()

值得一提的是如果获取的是json格式的数据,可以使用python自带的json库来解析成一个字典或列表:

data = json.loads(response.body)

4. 数据存储

可以使用twisted提供的数据库库来维护一个连接池:

class CnblogPipeline(object):
def __init__(self):
self.dbpool = adbapi.ConnectionPool('MySQLdb',
host='localhost',
db='cnblog',
user='root',
passwd='root',
cursorclass=MySQLdb.cursors.DictCursor,
charset='utf8',
use_unicode=True) def process_item(self, item, spider):
self.dbpool.runInteraction(self.cnblog_insert, item)
return item def cnblog_insert(self, cur, item):
try:
cur.execute('insert into ***')
exception MySQLdb.Error, e:
logging.info("cnblog_insert:%s" % str(e))

如果爬的是社交网站这种有着树型结构关系的网站的话,mongodb其符合人的思维的存储方式让其成为首选。

如果使用mysql的话记得将innodb_flush_log_at_trx_commit这个参数置为0(每一秒读写一次数据和log),可以大大提高读写速度。


5. scrapy小知识点

  • Request传递消息。在Request中加入meta,即可将meta传递给response。
Request(url, meta={'how': 'ok'}, callback=self.parse_page)

def parse_page(self, response):
print response.meta['how']
  • CrawlSpider。都知道在写自己的spider的时候需要继承scrapy的spider,除了scrapy.Spider外,scrapy还提供了好几种spider,其中CrawlSpider算是比较常用的。CrawlSpider的优势在于可以用rules方便地规定新的url的样子,即通过正则匹配来约束url。并且不需要自己生成新的url,CrawlSpider会自己寻找源码中所有符合要求的新url的。另外,rules的回调方法名字最好不要叫parse。
class CnblogSpider(CrawlSpider):
name = "cnblog_spider"
allowed_domain = ["cnblog.com"] start_urls = ["http://www.cnblogs.com/rubinorth"] rules = [
Rule(LinkExtractor(allow=r"http://www.cnblogs.com/rubinorth/p/\d+\.html"),
callback="parse_page", follow=True)
]
  • parse中既返回item又生成新的request。平时在parse中return item即可返回item,return request则生成新的request请求。如果我们将return换为yield的话即可既返回item又生成新的request。注意一旦使用了yield,那么parse方法中就不能有return了。
def parse_page(self, response):
item = CnblogItem()
****
yield item
yield Request(new_url, callback=self.parse_page)
  • 每个spider不同设置。在spider中加入custom_settings即可覆盖settings.py中相应的设置,这样的话在settings.py中只需要放一些公用的设置就行了。最常用的就是设置每个spider的pipeline。
custom_settings={
'ITEM_PIPELINES' : {
'cnblog_project.pipelines.CnblogPipeline': 300,
}
}
  • 读取自己的设置。不管在spider中还是pipeline中,都可以写from_crawler这个方法(注意spider中参数数目不同)。此方法在初始化阶段由scrapy自己调用,其最大的作用就是从settings.py读取自己的设置了。下面的代码从settings.py中读取了MONGO_URI。
class MongoPipeline(object):

    def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri @classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI')
)
  • 顺序。settings.py中middleware和pipeline设置的时候需要在后面跟上一个数字,而这个数字的含义就是调用的顺序,数字越小越早调用。
DOWNLOADER_MIDDLEWARES = {
'cnblog_project.my_mv.middleware.UserAgentMiddleware': 543,
'cnblog_project.my_mv.middleware.ProxyMiddleware':544,
}
  • pipeline中spider.name的应用。pipeline中的process_item中可以根据spider.name来对不同的item进行不同的处理。
def process_item(self, item, spider):
if spider.name == 'a':
****
if spider.name == 'b':
****
  • 多个pipeline处理一个item。pipeline中的process_item方法必须返回一个item或者raise一个DropItem的异常,如果返回item的话这个item将会被之后的pipeline接收到。
def process_item(self, item, spider):
return item
  • 之后可能会有添加。

其实这些在scrapy的官方文档都有提及,在此只是总结一些常用的知识点。若想更深入地了解scrapy,定然是阅读其官方文档最好了。:)


6. scrapy_redis简介

scrapy_redis是一个分布式爬虫的解决方案。其思想为多个爬虫共用一个爬取队列,此队列使用redis存储,因为redis是一个内存数据库,所以速度上与单机的队列相差不大。

那么,scrapy_redis到底对scrapy做了什么修改,达到分布式的目的呢?

查看github上面的源码,可以发现其功能性代码集中在scheduler.py,dupefilter.py和queue.py中,分别是调度器(部分功能),去重,以及redis队列的实现。scrapy_redis就是将这些功能代替了scrapy原本的功能(并没有修改scrapy源码,只需要在settings.py中进行设置即可),从而达到了分布式的效果。


参考资料

scrapy官中文档

转载请注明出处:http://www.cnblogs.com/rubinorth/

网页爬虫--scrapy进阶的更多相关文章

  1. 网页爬虫--scrapy入门

    本篇从实际出发,展示如何用网页爬虫.并介绍一个流行的爬虫框架~ 1. 网页爬虫的过程 所谓网页爬虫,就是模拟浏览器的行为访问网站,从而获得网页信息的程序.正因为是程序,所以获得网页的速度可以轻易超过单 ...

  2. Node.js 网页爬虫再进阶,cheerio助力

    任务还是读取博文标题. 读取app2.js // 内置http模块,提供了http服务器和客户端功能 var http=require("http"); // cheerio模块, ...

  3. scrapy进阶(CrawlSpider爬虫__爬取整站小说)

    # -*- coding: utf-8 -*- import scrapy,re from scrapy.linkextractors import LinkExtractor from scrapy ...

  4. Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱(转)

    原文:http://www.52nlp.cn/python-网页爬虫-文本处理-科学计算-机器学习-数据挖掘 曾经因为NLTK的缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然开 ...

  5. [resource-]Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱

    reference: http://www.52nlp.cn/python-%e7%bd%91%e9%a1%b5%e7%88%ac%e8%99%ab-%e6%96%87%e6%9c%ac%e5%a4% ...

  6. python爬虫Scrapy(一)-我爬了boss数据

    一.概述 学习python有一段时间了,最近了解了下Python的入门爬虫框架Scrapy,参考了文章Python爬虫框架Scrapy入门.本篇文章属于初学经验记录,比较简单,适合刚学习爬虫的小伙伴. ...

  7. python爬虫scrapy项目详解(关注、持续更新)

    python爬虫scrapy项目(一) 爬取目标:腾讯招聘网站(起始url:https://hr.tencent.com/position.php?keywords=&tid=0&st ...

  8. 第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息

    第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息 crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多 ...

  9. 第三百三十一节,web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令

    第三百三十一节,web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令 Scrapy框架安装 1.首先,终端执行命令升级pip: python -m pip install --u ...

随机推荐

  1. Linux gcc命令

    一.简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objectiv ...

  2. Linux Purify命令

    一.简介 在C/C++的软件开发中,没有任何一种工具可以让你的应用程序避免引入内存问题,但是我们可以使用诸如Purify这样的工具对已经做好了的程序进行内存问题的检查.Purify的强大之处是可以找到 ...

  3. C++STL之迭代器2

    在学习c++ STL的时候,整天碰到迭代器,也整天用,但是,到底它是个什么东西,很多人没有一个认识.这里我通过几个小的DEMO,来看看迭代器.首先我实现了一个十分简陋的vector类: templat ...

  4. 巧用开发者工具的控制台来调试页面中的js语句

    因为要弄某网页的一个自动登陆工具,所以需要对此网页中的元素利用js进行选取和操作,复杂的js选取如果直接在头脑中想很容易出错,而且一旦出错也不好判断错误原因. 而浏览器带的开发者工具的控制台功能,就给 ...

  5. 探索 OpenStack 之(14):OpenStack 中 RabbitMQ 的使用

    本文是 OpenStack 中的 RabbitMQ 使用研究 两部分中的第一部分,将介绍 RabbitMQ 的基本概念,即 RabbitMQ 是什么.第二部分将介绍其在 OpenStack 中的使用. ...

  6. [转]Performance Analysis Using SQL Server 2008 Activity Monitor Tool

    本文转自:https://www.mssqltips.com/sqlservertip/1917/performance-analysis-using-sql-server-2008-activity ...

  7. Java向上转型与向下转型

    一.向上转型 例如:Parent p=new Son(); 这样引用p只能调用子类中重载父类的方法:但属性是父类的:如果想调用子类属性的话,可以用getter()方法. 二.向下转型 子类对象的父类引 ...

  8. 【问题&解决】解决 Android SDK下载和更新失败“Connection to https://dl-ssl.google.com refused”的问题

    缘由: 更新sdk,遇到了更新下载失败问题: Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xmlFetche ...

  9. 怎样Zbrush 4R7中添加和删除SubTool

    添加或删除SubTool在ZBrush®软件中是非常简单易操作的,通常在用SubTool面板已经给我们提供了相应的命令来对其进行操作,它能够将一个或多个格式为ZTL的文件同时添加进SubTool里. ...

  10. [cocos2dx]让CCScrollView支持分页

    [cocos2dx]让CCScrollView支持分页 做过IOS开发的朋友, 肯定知道UIScrollView有一个isPaged属性. 当设置其为true的时候, 滑动会自动分页. 即, 每次滑动 ...