放假后看了两周的Web Scraping with Python之前几章看的很happy,尝试了许多小程序,等看到API和Database后开始有点空中楼阁的感觉,觉得应该把前面的内容学好,实践一些后再往下走。所以打算从Scrapy开始一点一点精通Python web crawler.
scrapy不仅可以用于web scraping,也同时可以应用API,之前Twitter和Google的API看的云山雾罩,说不定在此能有一些突破。
然后再强调一下现在windows 7 下py3好像不支持scrapy,至少我的电脑上不行,所以解释器一定换成2.7版本的。推荐用2.7.11及以后版本因为自带pip省去了安装上的一点麻烦。
先看书上的第一个例子
import scrapy
class StackOverflowSpider(scrapy.Spider):
<span style="white-space:pre"> </span>name = 'stackoverflow'
<span style="white-space:pre"> </span>start_urls = ['http://stackoverflow.com/questions?sort=votes']
def parse(self, response):
<span style="white-space:pre"> </span>for href in response.css('.question-summary h3 a::attr(href)'):
<span style="white-space:pre"> </span>full_url = response.urljoin(href.extract())
<span style="white-space:pre"> </span>yield scrapy.Request(full_url, callback=self.parse_question)
def parse_question(self, response):
<span style="white-space:pre"> </span>yield {
<span style="white-space:pre"> </span>'title': response.css('h1 a::text').extract()[0],
<span style="white-space:pre"> </span>'votes': response.css('.question .vote-count-post::text').extract()[0],
<span style="white-space:pre"> </span>'body': response.css('.question .post-text').extract()[0],
<span style="white-space:pre"> </span>'tags': response.css('.question .post-tag::text').extract(),
<span style="white-space:pre"> </span>'link': response.url,
<span style="white-space:pre"> </span>}
然后再命令行下用
scrapy runspider stackoverflow_spider.py -o top-stackoverflow-questions.json
执行
这里 -o 及后面的作用就是把读到的数据存入当前目录下指定名字的json文件中
json问价打开之后就是这个样子。(对于json具体的用法什么的我现在还是小白不太懂,不过感觉和xml与html都挺像的)
其中
start_urls这个属性确定了crawler开始访问的URL。cralwer先根据这个属性making requests,然后调用parse这个回调方法
在parse中通过CSS selector来提取链接。
在这个过程中同时yield了许多requests
parse_question作为一个request的结束
scrapy的一个优点就是异步处理(asynchronously),也就是说scrapy不用等一个request处理完再进行下一个。它可以同时进行多个requests的处理,即使其中一个request报错或失败也不影响其它的requests。最后parse_question 抓取我们要的question data并生成字典,然后写入一个JSON文件中。
-------------------------------------------------------------------------
下面再来一个书上的tutorial,来说用scrapy的基本步骤
1 创建新项目
假如我们要创建一个名叫tutorial的新项目
scrapy startproject tutorial
这个新项目的基本结构就是这个样子
2 定义Item
item的作用是容纳抓取到的数据,其作用类似于python的dict,但是item的功能更优化一些,能更好地处理typo之类的东西
item的声明方法就是定义一个scrapy.Item类对象,其中定义的属性是scrapy.Field()对象。
3 第一个Spider
Spiders是我们定义的用来让scrapy从特定域名中抓取数据的类。
在这个类中我们需要定义url列表,定义如何follow链接,并定义如何通过分析页面内容来提取items
每个Spider是scrapy.Spider的一个类对象,通过属性name来区分,这也是在cmd中运行一个spider时用的名字
下面在 tutorial/spiders目录下新建一个文件dmoz_spider.py
start_urls是我们要抓取的网页url
parse定义了我们如何处理得到的数据,可以看见这里是把每个url的数据写入html文件中
import scrapy
class DmozSpider(scrapy.Spider):
name = "dmoz"
allowed_domains = ["dmoz.org"]
start_urls = [
"http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
"http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
]
def parse(self, response):
filename = response.url.split("/")[-2] + '.html'
with open(filename, 'wb') as f:
f.write(response.body)
scrapy crawl dmoz
cmd中执行结果如下,
在这可以看到spider对指定的两个网址都进行了抓取。
注意这块两个网页的referer都是None,现在我还不太明白是什么意思不过似乎很重要
最后在目录下生成了两个文件
后台如何运行?
Scrapy为start_urls这个属性中的每一个URL都生成一个scrapy.Request对象,并把parse方法分配为它们的回调函数。
这些对象经过处理后返回scrapy.http.Response对象给parse方法。
提取Items
未完待续...