scrapy-入门篇

Scrapy教程01- 入门篇

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘,
信息处理或存储历史数据等一系列的程序中。其最初是为了页面抓取(更确切来说,网络抓取)所设计的,
也可以应用在获取API所返回的数据(比如Web Services)或者通用的网络爬虫。

Scrapy也能帮你实现高阶的爬虫框架,比如爬取时的网站认证、内容的分析处理、重复抓取、分布式爬取等等很复杂的事。

安装scrapy

我的测试环境是centos6.5

升级python到最新版的2.7,下面的所有步骤都切换到root用户

由于scrapy目前只能运行在python2上,所以先更新centos上面的python到最新的
Python 2.7.11
具体方法请google下很多这样的教程。

先安装一些依赖软件

1
2
3
yum install python-devel
yum install libffi-devel
yum install openssl-devel

然后安装pyopenssl库

1
pip install pyopenssl

安装xlml

1
2
3
yum install python-lxml
yum install libxml2-devel
yum install libxslt-devel

安装service-identity

1
pip install service-identity

安装twisted

1
pip install scrapy

安装scrapy

1
pip install scrapy -U

测试scrapy

1
scrapy bench

最终成功,太不容易了!

简单示例

创建一个python源文件,名为stackoverflow.py,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import scrapy


class StackOverflowSpider(scrapy.Spider):
name = 'stackoverflow'
start_urls = ['http://stackoverflow.com/questions?sort=votes']

def parse(self, response):
for href in response.css('.question-summary h3 a::attr(href)'):
full_url = response.urljoin(href.extract())
yield scrapy.Request(full_url, callback=self.parse_question)

def parse_question(self, response):
yield {
'title': response.css('h1 a::text').extract()[0],
'votes': response.css('.question .vote-count-post::text').extract()[0],
'body': response.css('.question .post-text').extract()[0],
'tags': response.css('.question .post-tag::text').extract(),
'link': response.url,
}

运行:

1
scrapy runspider stackoverflow_spider.py -o top-stackoverflow-questions.json

结果类似下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[{
"body": "... LONG HTML HERE ...",
"link": "http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array",
"tags": ["java", "c++", "performance", "optimization"],
"title": "Why is processing a sorted array faster than an unsorted array?",
"votes": "9924"
},
{
"body": "... LONG HTML HERE ...",
"link": "http://stackoverflow.com/questions/1260748/how-do-i-remove-a-git-submodule",
"tags": ["git", "git-submodules"],
"title": "How do I remove a Git submodule?",
"votes": "1764"
},
...]

当你运行scrapy runspider somefile.py这条语句的时候,Scrapy会去寻找源文件中定义的一个spider并且交给爬虫引擎来执行它。
start_urls属性定义了开始的URL,爬虫会通过它来构建初始的请求,返回response后再调用默认的回调方法parse并传入这个response。
我们在parse回调方法中通过使用css选择器提取每个提问页面链接的href属性值,然后yield另外一个请求,
并注册parse_question回调方法,在这个请求完成后被执行。

处理流程图:

2020-1-19-17-30-31

Scrapy的一个好处是所有请求都是被调度并异步处理,就算某个请求出错也不影响其他请求继续被处理。

我们的示例中将解析结果生成json格式,你还可以导出为其他格式(比如XML、CSV),或者是将其存储到FTP、Amazon S3上。
你还可以通过pipeline
将它们存储到数据库中去,这些数据保存的方式各种各样。

Scrapy特性一览

你已经可以通过Scrapy从一个网站上面爬取数据并将其解析保存下来了,但是这只是Scrapy的皮毛。
Scrapy提供了更多的特性来让你爬取更加容易和高效。比如:

  1. 内置支持扩展的CSS选择器和XPath表达式来从HTML/XML源码中选择并提取数据,还能使用正则表达式
  2. 提供交互式shell控制台试验CSS和XPath表达式,这个在调试你的蜘蛛程序时很有用
  3. 内置支持生成多种格式的订阅导出(JSON、CSV、XML)并将它们存储在多个位置(FTP、S3、本地文件系统)
  4. 健壮的编码支持和自动识别,用于处理外文、非标准和错误编码问题
  5. 可扩展,允许你使用signals
    和友好的API(middlewares, extensions, 和pipelines)来编写自定义插件功能。
  6. 大量的内置扩展和中间件供使用:
    • cookies and session handling
    • HTTP features like compression, authentication, caching
    • user-agent spoofing
    • robots.txt
    • crawl depth restriction
    • and more
  7. 还有其他好多好东东,比如可重复利用蜘蛛来爬取Sitemaps和XML/CSV订阅,
    一个跟爬取元素关联的媒体管道来
    自动下载图片
    一个缓存DNS解析器等等。
阅读全文
scrapy-内置服务

Scrapy教程07- 内置服务

Scrapy使用Python内置的的日志系统来记录事件日志。
日志配置

1
2
3
4
5
6
7
LOG_ENABLED = true
LOG_ENCODING = "utf-8"
LOG_LEVEL = logging.INFO
LOG_FILE = "log/spider.log"
LOG_STDOUT = True
LOG_FORMAT = "%(asctime)s [%(name)s] %(levelname)s: %(message)s"
LOG_DATEFORMAT = "%Y-%m-%d %H:%M:%S"

使用也很简单

1
2
3
import logging
logger = logging.getLogger(__name__)
logger.warning("This is a warning")

阅读全文
scrapy-模拟登录

Scrapy教程11- 模拟登录

有时候爬取网站的时候需要登录,在Scrapy中可以通过模拟登录保存cookie后再去爬取相应的页面。这里我通过登录github然后爬取自己的issue列表来演示下整个原理。

要想实现登录就需要表单提交,先通过浏览器访问github的登录页面https://github.com/login
然后使用浏览器调试工具来得到登录时需要提交什么东西:

2020-1-19-17-31-18

我这里使用chrome浏览器的调试工具,F12打开后选择Network,并将Preserve log勾上。
我故意输入错误的用户名和密码,得到它提交的form表单参数还有POST提交的URL:

阅读全文
scrapy-动态配置爬虫

Scrapy教程10- 动态配置爬虫

有很多时候我们需要从多个网站爬取所需要的数据,比如我们想爬取多个网站的新闻,将其存储到数据库同一个表中。我们是不是要对每个网站都得去定义一个Spider类呢?
其实不需要,我们可以通过维护一个规则配置表或者一个规则配置文件来动态增加或修改爬取规则,然后程序代码不需要更改就能实现多个网站爬取。

要这样做,我们就不能再使用前面的scrapy crawl test这种命令了,我们需要使用编程的方式运行Scrapy spider,参考官方文档

脚本运行Scrapy

可以利用scrapy提供的核心API通过编程方式启动scrapy,代替传统的scrapy crawl启动方式。

Scrapy构建于Twisted异步网络框架基础之上,因此你需要在Twisted reactor里面运行。

首先你可以使用scrapy.crawler.CrawlerProcess这个类来运行你的spider,这个类会为你启动一个Twisted reactor,并能配置你的日志和shutdown处理器。所有的scrapy命令都使用这个类。

1
2
3
4
5
6
7
8
import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

process = CrawlerProcess(get_project_settings())

process.crawl(MySpider)
process.start() # the script will block here until the crawling is finished

然后你就可以直接执行这个脚本

1
python run.py

阅读全文
scrapy-部署

Scrapy教程09- 部署

本篇主要介绍两种部署爬虫的方案。如果仅仅在开发调试的时候在本地部署跑起来是很容易的,不过要是生产环境,爬虫任务量大,并且持续时间长,那么还是建议使用专业的部署方法。主要是两种方案:

部署到Scrapyd

Scrapyd是一个开源软件,用来运行蜘蛛爬虫。它提供了HTTP API的服务器,还能运行和监控Scrapy的蜘蛛

要部署爬虫到Scrapyd,需要使用到scrapyd-client部署工具集,下面我演示下部署的步骤

Scrapyd通常以守护进程daemon形式运行,监听spider的请求,然后为每个spider创建一个进程执行scrapy crawl myspider,同时Scrapyd还能以多进程方式启动,通过配置max_procmax_proc_per_cpu选项

安装

使用pip安装

1
pip install scrapyd

在ubuntu系统上面

1
apt-get install scrapyd

阅读全文
Algolia