安装: pip install scrapy
(1)启动项目
安装好 scrapy 后,我们可以运行 startproject 命令生成该项目的默认结构。具体步骤为:打开终端进入想要存储 scrapy 项目的目录,然后运行 scrapy startproject <project name> 。比如使用 example 作为项目名
scrapy startproject example
cd example 就会发现下面的文件结构:
__init__.py
items.py :定义了待抓取域的模型
setting.py :定义一些设置,比如用户代理,爬取延时等
spiders/ :该目录存储实际的爬虫代码
(2)定义模型
默认情况下,example/items.py 文件包含如下代码
import scrapy
class ExampleItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass
ExampleItem 类是一个模板,需要将其中的内容替换为爬虫运行时想要抓取的信息。我们抓取国家名称和人口数量,修改 items.py 如下:
import scrapy
class ExampleItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
population = scrapy.Field()
(3)创建爬虫
通过 genspider 命令,传入爬虫名,域名,以及可选的参数模板,就可以在 spiders 目录生成初始模板
scrapy genspider country example.webscraping.com --template=crawl
这里使用内置的 crawl 模板,可以生成更接近我们想要的爬虫的初始版本,自动生成 spiders/country.py 如下:
import scrapy
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.contrib.spiders import CrawlSpider,Rule
from example.items import ExampleItem
class CountrySpider(CrawlSpider):
name = "country" # 定义爬虫名称
start_urls = ["http://www.example.webscraping.com/"] # 定义了爬虫起始 url 列表,这里要去掉 www.
allowed_domains = ["example.webscraping.com"] # 定义可以爬取的域名列表,如果没有,则可以爬取任何域名
rules = ( # 为一个正则表达式集合,告知爬虫需要跟踪哪些链接
Rule(LinkExtractor(allow=r'Items/),
callback='parse_item',follow=True),
)
(4) 爬虫设置
建议在 settings.py 增加一些爬虫限制设置,比如增加如下两行:
CONCURRENT_REQUESTS_PER_DOMAIN = 1 # 每秒请求次数
DOWNLOAD_DECAY = 5 # 下载延时 5 秒
(5)运行爬虫并保存至 csv
scrapy crawl country --output=countries.csv -s LOG_LEVEL=INFO
(6)中断与恢复爬虫
scrapy 内置了对暂停与恢复爬取的支持,这样就不需要再修改示例爬虫了。要开启该功能,只需要定义用于保存爬虫当前状态目录的 JOBDIR 设置即可。
scrapy crawl country -s LOG_LEVEL=INFO -s JOBDIR=crawls/country
中断后再次执行该命令即可恢复爬虫。。。
使用 Portia 编写可视化爬虫
安装 Portia 文档:https://github.com/scrapinghub/portia#running-portia
安装完成后,在浏览器中输入: http://localhost:9001/static/main.html 就可以访问到 Portia 工具。
使用 scrapely 实现自动化抓取
安装: pip install scrapely
示例代码如下:
from scrapely import Scraper
s = Scraper()
train_url = "http://example.webscraping.com/view/Afghanistan-1"
s.train(train_url,{"name":"Afghanistan","population":"29,121,286"})
test_url = "http://example.webscraping.com/view/United-Kingdom-239"
print s.scrape(test_url)
# 期望输出 [{"name":"United Kingdom","population":"62,348,447"}]
但实际上运行失败了。在测试 scrapely 时,使用的网页应具有良好的结构,每个数据类型的标签和属性都是独立的,scrapely 才可以正确的训练模型。但是,对于复杂的模型,scrapely 可能会定位失败。所以应当“谨慎训练”。