3

爬虫(9) - Scrapy框架(1) | Scrapy 异步网络爬虫框架 - 葛老头

 1 year ago
source link: https://www.cnblogs.com/gltou/p/16400449.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

什么是Scrapy

  • 基于Twisted的异步处理框架
  • 纯python实现的爬虫框架
  • 基本结构:5+2框架,5个组件,2个中间件

 

2281865-20220622144950841-1472507199.png

5个组件:

  • Scrapy Engine:引擎,负责其他部件通信 进行信号和数据传递;负责Scheduler、Downloader、Spiders、Item Pipeline中间的通讯信号和数据的传递,此组件相当于爬虫的“大脑”,是整个爬虫的调度中心
  • Scheduler:调度器,将request请求排列入队,当引擎需要交还给引擎,通过引擎将请求传递给Downloader;简单地说就是一个队列,负责接收引擎发送过来的 request请求,然后将请求排队,当引擎需要请求数据的时候,就将请求队列中的数据交给引擎。初始的爬取URL和后续在页面中获取的待爬取的URL将放入调度器中,等待爬取,同时调度器会自动去除重复的URL(如果特定的URL不需要去重也可以通过设置实现,如post请求的URL)
  • Downloader:下载器,将引擎engine发送的request进行接收,并将response结果交还给引擎engine,再由引擎传递给Spiders处理
  • Spiders:解析器,它负责处理所有responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器);同时也是入口URL的地方
  • Item Pipeline:数据管道,就是我们封装去重类、存储类的地方,负责处理 Spiders中获取到的数据并且进行后期的处理,过滤或者存储等等。当页面被爬虫解析所需的数据存入Item后,将被发送到项目管道(Pipeline),并经过几个特定的次序处理数据,最后存入本地文件或存入数据库

2个中间件:

  • Downloader Middlewares:下载中间件,可以当做是一个可自定义扩展下载功能的组件,是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response。通过设置下载器中间件可以实现爬虫自动更换user-agent、IP等功能。
  • Spider Middlewares:爬虫中间件,Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。自定义扩展、引擎和Spider之间通信功能的组件,通过插入自定义代码来扩展Scrapy功能。

 Scrapy操作文档(中文的):https://www.osgeo.cn/scrapy/topics/spider-middleware.html

Scrapy框架的安装

cmd窗口,pip进行安装

pip install scrapy

2281865-20220622144115902-591510172.png

Scrapy框架安装时常见的问题

找不到win32api模块----windows系统中常见

pip install pypiwin32

创建Scrapy爬虫项目

scrapy startproject xxx项目名称

实例:

scrapy startproject tubatu_scrapy_project

2281865-20220622154649893-1468217369.png

 

2281865-20220622155204402-1254423692.png

scrapy.cfg:项目的配置文件,定义了项目配置文件的路径等配置信息

  • 【settings】:定义了项目的配置文件的路径,即./tubatu_scrapy_project/settings文件
  • 【deploy】:部署信息

2281865-20220622160214454-1616271586.png
  • items.py:就是我们定义item数据结构的地方;也就是说我们想要抓取哪些字段,所有的item定义都可以放到这个文件中
  • pipelines.py:项目的管道文件,就是我们说的数据处理管道文件;用于编写数据存储,清洗等逻辑,比如将数据存储到json文件,就可以在这边编写逻辑
  • settings.py:项目的设置文件,可以定义项目的全局设置,比如设置爬虫的 USER_AGENT ,就可以在这里设置;常用配置项如下:
    • ROBOTSTXT_OBEY :是否遵循ROBTS协议,一般设置为False
    • CONCURRENT_REQUESTS :并发量,默认是32个并发
    • COOKIES_ENABLED :是否启用cookies,默认是False
    • DOWNLOAD_DELAY :下载延迟
    • DEFAULT_REQUEST_HEADERS :默认请求头
    • SPIDER_MIDDLEWARES :是否启用spider中间件
    • DOWNLOADER_MIDDLEWARES :是否启用downloader中间件
    • 其他详见链接
  • spiders目录:包含每个爬虫的实现,我们的解析规则写在这个目录下,即爬虫的解析器写在这个目录下
  • middlewares.py:定义了 SpiderMiddleware和DownloaderMiddleware 中间件的规则;自定义请求、自定义其他数据处理方式、代理访问等

自动生成spiders模板文件

cd到spiders目录下,输出如下命令,生成爬虫文件:

scrapy genspider 文件名 爬取的地址

2281865-20220622194542701-501268431.png

2281865-20220622194705119-806132516.png

方式一:cmd启动

cd到spiders目录下,执行如下命令,启动爬虫:

scrapy crawl 爬虫名

2281865-20220622200255323-134289728.png

方式二:py文件启动

在项目下创建main.py文件,创建启动脚本,执行main.py启动文件,代码示例如下:

code-爬虫文件👇

import scrapy


class TubatuSpider(scrapy.Spider):
    #名称不能重复
    name = 'tubatu'
    #允许爬虫去抓取的域名
    allowed_domains = ['xiaoguotu.to8to.com']
    #项目启动之后要启动的爬虫文件
    start_urls = ['https://xiaoguotu.to8to.com/pic_space1?page=1']

    #默认的解析方法
    def parse(self, response):
        print(response.text)

code-启动文件👇

from scrapy import cmdline

#在我们scrapy项目里面,为了方便运行scrapy的项目的时候创建的文件
#使用cmdlie.execute()方法执行爬虫启动命令:scrapy crawl 爬虫名
cmdline.execute("scrapy crawl tubatu".split())  #execute方法需要运行的每一个命令为单独的一个字符串,如:cmdline.execute(['scrapy', 'crawl', 'tubatu']),所以如果命令为一整个字符串时,需要split( )进行分割;#

code-运行结果👇

2281865-20220622201420445-574844410.png

爬取土巴兔装修网站信息。将爬取到的数据存入到本地MongoDB数据库中;

下图👇为项目机构,标蓝的文件就是此次code的代码

2281865-20220627204237933-424503324.png

tubatu.py

 1 import scrapy
 2 from tubatu_scrapy_project.items import TubatuScrapyProjectItem
 3 import re
 4 
 5 class TubatuSpider(scrapy.Spider):
 6 
 7     #名称不能重复
 8     name = 'tubatu'
 9     #允许爬虫去抓取的域名,超过这个目录就不允许抓取
10     allowed_domains = ['xiaoguotu.to8to.com','wx.to8to.com','sz.to8to.com']
11     #项目启动之后要启动的爬虫文件
12     start_urls = ['https://xiaoguotu.to8to.com/pic_space1?page=1']
13 
14 
15     #默认的解析方法
16     def parse(self, response):
17         # response后面可以直接使用xpath方法
18         # response就是一个Html对象
19         pic_item_list = response.xpath("//div[@class='item']")
20         for item in pic_item_list[1:]:
21             info = {}
22             # 这里有一个点不要丢了,是说明在当前Item下面再次使用xpath
23             # 返回的不仅仅是xpath定位中的text()内容,需要再过滤;返回如:[<Selector xpath='.//div/a/text()' data='0元搞定设计方案,限名额领取'>] <class 'scrapy.selector.unified.SelectorList'>
24             # content_name = item.xpath('.//div/a/text()')
25 
26             #使用extract()方法获取item返回的data信息,返回的是列表
27             # content_name = item.xpath('.//div/a/text()').extract()
28 
29             #使用extract_first()方法获取名称,数据;返回的是str类型
30             #获取项目的名称,项目的数据
31             info['content_name'] = item.xpath(".//a[@target='_blank']/@data-content_title").extract_first()
32 
33             #获取项目的URL
34             info['content_url'] = "https:"+ item.xpath(".//a[@target='_blank']/@href").extract_first()
35 
36             #项目id
37             content_id_search = re.compile(r"(\d+)\.html")
38             info['content_id'] = str(content_id_search.search(info['content_url']).group(1))
39 
40             #使用yield来发送异步请求,使用的是scrapy.Request()方法进行发送,这个方法可以传cookie等,可以进到这个方法里面查看
41             #回调函数callback,只写方法名称,不要调用方法
42             yield scrapy.Request(url=info['content_url'],callback=self.handle_pic_parse,meta=info)
43 
44         if response.xpath("//a[@id='nextpageid']"):
45             now_page = int(response.xpath("//div[@class='pages']/strong/text()").extract_first())
46             next_page_url="https://xiaoguotu.to8to.com/pic_space1?page=%d" %(now_page+1)
47             yield scrapy.Request(url=next_page_url,callback=self.parse)
48 
49 
50     def handle_pic_parse(self,response):
51         tu_batu_info = TubatuScrapyProjectItem()
52         #图片的地址
53         tu_batu_info["pic_url"]=response.xpath("//div[@class='img_div_tag']/img/@src").extract_first()
54         #昵称
55         tu_batu_info["nick_name"]=response.xpath("//p/i[@id='nick']/text()").extract_first()
56         #图片的名称
57         tu_batu_info["pic_name"]=response.xpath("//div[@class='pic_author']/h1/text()").extract_first()
58         #项目的名称
59         tu_batu_info["content_name"]=response.request.meta['content_name']
60         # 项目id
61         tu_batu_info["content_id"]=response.request.meta['content_id']
62         #项目的URL
63         tu_batu_info["content_url"]=response.request.meta['content_url']
64         #yield到piplines,我们通过settings.py里面启用,如果不启用,将无法使用
65         yield tu_batu_info

items.py

 1 # Define here the models for your scraped items
 2 #
 3 # See documentation in:
 4 # https://docs.scrapy.org/en/latest/topics/items.html
 5 
 6 import scrapy
 7 
 8 
 9 class TubatuScrapyProjectItem(scrapy.Item):
10     # define the fields for your item here like:
11     # name = scrapy.Field()
12 
13     #装修名称
14     content_name=scrapy.Field()
15     #装修id
16     content_id = scrapy.Field()
17     #请求url
18     content_url=scrapy.Field()
19     #昵称
20     nick_name=scrapy.Field()
21     #图片的url
22     pic_url=scrapy.Field()
23     #图片的名称
24     pic_name=scrapy.Field()

piplines.py

 1 # Define your item pipelines here
 2 #
 3 # Don't forget to add your pipeline to the ITEM_PIPELINES setting
 4 # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
 5 
 6 
 7 # useful for handling different item types with a single interface
 8 from itemadapter import ItemAdapter
 9 
10 from pymongo import MongoClient
11 
12 class TubatuScrapyProjectPipeline:
13 
14     def __init__(self):
15         client = MongoClient(host="localhost",
16                              port=27017,
17                              username="admin",
18                              password="123456")
19         mydb=client['db_tubatu']
20         self.mycollection = mydb['collection_tubatu']
21 
22     def process_item(self, item, spider):
23         data = dict(item)
24         self.mycollection.insert_one(data)
25         return item

settings.py

2281865-20220627204550658-625647551.png

main.py

1 from scrapy import cmdline
2 
3 #在我们scrapy项目里面,为了方便运行scrapy的项目的时候创建的文件
4 #使用cmdlie.execute()方法执行爬虫启动命令:scrapy crawl 爬虫名
5 cmdline.execute("scrapy crawl tubatu".split())  #execute方法需要运行的每一个命令为单独的一个字符串,如:cmdline.execute(['scrapy', 'crawl', 'tubatu']),所以如果命令为一整个字符串时,需要split( )进行分割;#

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK