天天看点

异步和多线程_第十一章 Scrapy框架:多线程+异步

异步和多线程_第十一章 Scrapy框架:多线程+异步

简介

Scrapy 框架

  1. Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架。
  2. 用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片。 (提高请求效率)
  3. Scrapy 使用了Twisted(aiohttp)异步网络框架来处理网络通讯,可以加快下载速度,并且包含了各种中间件接口,可以灵活的完成各种需求。

安装

  1. pip install --upgrade pip 建议首先更新pip 再安装下列依赖库 否则可能会遇到诸多错误:
2. pip install twisted

安装 twisted可能会遇到这样问题

building 'twisted.test.raiser' extension error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools

意思是说缺少C++的一些编译工具

所以这里建议大家直接安装编译好的twisted的whl文件 对应资源下载网址: https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted

下载twisted对应版本的whl文件,cp后面是python版本,amd64代表64位

运行命令: pip install C:UsersCRDownloadsTwisted-17.5.0-cp36-cp36m-win_amd64.whl (后边一部分是 whl文件的绝对路径)

3.

pip install lxml

lxml之前应该安装过 可以略过

4.

pip install pywin32

这个安装应该没问题

5.

pip install Scrapy

安装scrapy框架

如果中途报错,有TimeOut的字眼,应该是网络问题,重复安装几次就行

当然最省事的还是直接替换安装源 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名

知识

整体结构

异步和多线程_第十一章 Scrapy框架:多线程+异步

Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等

Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,

Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器),

Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.

Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件。

Spider Middlewares(Spider中间件):可以扩展操作引擎和Spider中间通信的功能组件

一次完整的请求流程

——> Spider(爬虫) ——> Spider Middlewares(Spider中间件) ——> Scrapy Engine(引擎) ——> Scheduler(调度器) ——> Scrapy Engine(引擎) ——> Downloader Middlewares(下载中间件) ——> Downloader(下载器) ——> Downloader Middlewares(下载中间件) ——> Scrapy Engine(引擎) ——> Spider Middlewares(Spider中间件) ——> Spider(爬虫) ——> Spider Middlewares(Spider中间件) ——> Item Pipeline(管道)

Scrapy完成爬虫需要涉及的文件和步骤

  1. 新建项目 (scrapy startproject xxx):新建一个新的爬虫项
  2. 明确目标(编写items.py):明确你想要抓取的目标
  3. 制作爬虫(spiders/xxspider.py):制作爬虫开始爬取网页
  4. 存储内容(pipelines.py):设计管道存储爬取内容

入门案例

项目创建

执行: 终端输入代码:scrapy startproject JobSpider

结果: 目录结构:

异步和多线程_第十一章 Scrapy框架:多线程+异步

确定目标

确定要爬取的网站和信息的url

抓取上海地区python招聘职位的情况,包括职位名称,公司名称,工作地点,薪资,发布时间:

目标地址: https://search.51job.com/list/020000,000000,0000,00,9,99,python,2,1.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare

1.打开项目中的item.py文件

异步和多线程_第十一章 Scrapy框架:多线程+异步

2.创建一个JobspiderItem类,继承scrapy.Item,构建item模型(model)。并且定义类型为scrapy.Field的类属性,用来保存爬取到的数据

class JobspiderItem(scrapy.Item):
    name = scrapy.Field()
    city = scrapy.Field()
    pub_date = scrapy.Field()
    salary = scrapy.Field()
           

制作爬虫

生成爬虫脚本模板

执行: 终端输入代码: 1.cd JobSpider

2.scrapy genspider pythonPosition http://51job.com

结果:

异步和多线程_第十一章 Scrapy框架:多线程+异步
脚本说明

打开上一步生成的模板

import scrapy

class PythonpositionSpider(scrapy.Spider):
    name = 'PythonPosition'
    allowed_domains = ['51job.com']
    start_urls = ['http://51job.com/',]

    def parse(self, response):
        pass
           

说明:

1.name="":这个爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字。

2.allow_domains=[]是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略。

3.start_urls=():爬取的URL元祖/列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始。

4.parse(self,response):解析的方法,每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下: 负责解析返回的网页数据(response.body),提取结构化数据(生成item) 生成需要下一页的URL请求。

修改代码
# 1.将start_urls的值修改为需要爬取的第一个url

start_urls=("https://search.51job.com/list/020000,000000,0000,00,9,99,python,2,1.html?,)


# 2.重写parse方法,用XPath提取数据
def parse(self, response):
#print(response.body)
job_list = response.xpath("//div[@class='dw_table']/div[@class='el']")

for each in job_list:
    name = each.xpath("normalize-space(./p/span/a/text())").extract()[0]
    city = each.xpath("./span[@class='t3']/text()").extract()[0]
    pub_date = each.xpath(".//span[@class='t5']/text()").extract()[0]
    salary = each.xpath(".//span[@class='t4']/text()").extract()
    if len(salary)>0:
        salary = salary[0]
    else:
        salary = ''

    item = JobspiderItem()
    item['name'] = name
    item['city'] = city
    item['pub_date'] = pub_date
    item['salary'] = salary
    # 将获取的数据交给pipeline 
    yield item
           

yield 不仅可以返回数据对象,也可以返回请求对象。

储存内容

打开存储管道文件:

异步和多线程_第十一章 Scrapy框架:多线程+异步

process_item 方法是用来处理每一个item数据对象的 close_spider 关闭爬虫时调用

# 写入CSV文件:
import csv
import codecs
class JobspiderPipeline(object):

    def __init__(self): 
        self.file = codecs.open('51job.csv', 'w', 'utf-8')
        self.wr = csv.writer(self.file, dialect="excel")
        self.wr.writerow(['name', 'pub_date', 'city', 'salary'])

    def process_item(self, item, spider): 
        self.wr.writerow([item['name'], item['pub_date'], item['city'], item['salary']])
        return item

    def close_spider(self, spider): 
        self.file.close()
           

在setting文件中启动储存管道

启用一个Item Pipeline组件

为了启用Item Pipeline组件,必须将它的类添加到settings.py文件ITEM_PIPELINES 配置,比如:

ITEM_PIPELINES = {
    #'mySpider.pipelines.SomePipeline': 300,"
    mySpider.pipelines.JsonPipeline":300
}
           

分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序通过pipeline,通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,组件的优先级越高)

异步和多线程_第十一章 Scrapy框架:多线程+异步

运行测试

1、创建run.py文件,和setting.py同级目录

2、添加代码:

from scrapy import cmdline

# 其中name参数为spider的name。
name = 'pythonPosition' cmd = 'scrapy crawl {0}'.format(name)
scrapy crawl pythonPosition
cmdline.execute(cmd.split())
           

3、run.py文件中右键运行。

任务

使用scrapy完成豆瓣电影top 250爬虫,电影的名称,简介,评分,引文等信息采集 https://movie.douban.com/top250?start=0&filter=2

异步和多线程_第十一章 Scrapy框架:多线程+异步