前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >scrapy全站爬取

scrapy全站爬取

作者头像
用户8447427
发布2022-08-18 15:40:11
6830
发布2022-08-18 15:40:11
举报
文章被收录于专栏:userlyz学习记录userlyz学习记录

笔记

代码语言:javascript
复制
-基于Spider的全站数据爬取
   -基于网站中某一模板下的全部页码对应的页面数据进行爬取
   -需求:爬取校花网中的照片的名称
   -实现方式:
        -将所有的url添加到start_urls  不推荐使用
        -自行手动进行请求的发送
            # 手动请求发送 callback回调函数是专门用作与数据解析
             yield scrapy.Request(url=new_url,callback=self.parse)
 -CrawlSpider的使用
        -创建一个工程
        -cd xxx
        -创建爬虫文件(CrawlSpider):
            -Scrapy genspider -t crawl xxx www.xxx.com
            -链接提取器
                -作用:根据指定的规则(allow)进行指定链接的提取
            -规则解析器
                -作用:将连接踢球去提取到的链接进行指定规则(callback)的解析
            -follow
                -follow=True; 可以将连接提取器,继续作用到链接提取器提取到的链接,所对用的页面中
                   即使有重复的url请求,我们的调度器中的过滤器,也会帮我们给过滤掉
-五大核心组件
	Spider:主要进行数据解析
	引擎: 所有的流数据都会流经引擎1、用作数据流处理的2、可以触发事务
		
	调度器:
		过滤器:将送过来的请求进行去重,去重之后放入队列等待下一步操作
		队列:
		最终给下载器中
	下载器:从互联网上去请求网页资源 异步的操作
	管道:进行持久化存储
-请求传参

    -使用场景:如果爬取解析的数据不在同一张页面中。(深度爬取)
    -需求:爬取boss直聘的岗位名称,岗位描述
视频截图
视频截图

图片爬取

需求:爬取站长素材的高清图片的爬取https://sc.chinaz.com/tupian/

笔记


基于scrapy框架爬取字符串类型的数据和爬取图片类型的数据有什么区别

​ 1、字符串,只需要xpath解析且提交管道进行持久化存储

​ 2、图片:xpath解析到图片src属性值。单独对图片地址发起请求获取图片二进制类型的数据数据

ImagesPipeline:

​ 只需要将img的src属性值进行解析,提交到管道,管道就会对图片的src进行请求发送获取到图片的二进制类型的数据,且话可以帮我们进行持久化存储

需求:爬取站长素材的图片爬取https://sc.chinaz.com/tupian/

使用流程:

​ 1、数据解析(图片的地址)

​ 2、将存储图片地址的item提交到指定的管道类

​ 3、管道文件之中自指定一个基于ImagesPipeLine的一个管道类

代码语言:javascript
复制
def get_media_requests(self, item, info):
    #就是可以根据图片地址,进行图片数据的请求
def file_path(self, request, response=None, info=None, *, item=None):
    #指定图片储存的路径
def item_completed(self, results, item, info):
    return item#返回给下一个即将执行的管道类

​ 4、在配置文件中:

​ 指定图片二点存储目录:IMAGES_STORE=’./imgs_lyz’

​ 指定开启的管道:自定制的管道类


img.py

代码语言:javascript
复制
import scrapy
from imgsPro.items import ImgsproItem

class ImgSpider(scrapy.Spider):
    name = 'img'
    allowed_domains = ['www.xxx.com']
    start_urls = ['https://sc.chinaz.com/tupian/']

    def parse(self, response):
        div_list=response.xpath('//*[@id="container"]/div')
        for div in div_list:
            # 注意:使用伪属性(这具体体现为,图片没在当前页面显示的话,就使用伪属性,显示出来之后才会去使用src属性)
            src=div.xpath('./div/a/img/@src2').extract_first()#//*[@id="container"]/div[1]/div/a/img/@src
            print(src)
            item = ImgsproItem()
            item ['src']='https:'+src#https://scpic1.chinaz.net/Files/pic/pic9/202112/apic37626_s.jpg
            yield item
        pass

pipelines.py

代码语言:javascript
复制
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
import scrapy
from itemadapter import ItemAdapter


# class ImgsproPipeline:
#     def process_item(self, item, spider):
#         return item

from scrapy.pipelines.images import ImagesPipeline
class imgsPipeline(ImagesPipeline):
    #重写父类中的三个方法
    def get_media_requests(self, item, info):
        #就是可以根据图片地址,进行图片数据的请求
        yield  scrapy.Request(item['src'])
    def file_path(self, request, response=None, info=None, *, item=None):
        #指定图片储存的路径
        img_name=request.url.split('/')[-1]
        return img_name
        pass
    def item_completed(self, results, item, info):
        return item#返回给下一个即将执行的管道类
        pass
    pass

items.py

代码语言:javascript
复制
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class ImgsproItem(scrapy.Item):
    # define the fields for your item here like:
    #
    src = scrapy.Field()
    pass

setting.py

代码语言:javascript
复制
USER_AGENT = 'ua检测'
ROBOTSTXT_OBEY = False
LOG_LEVEL='ERROR'

#去除注释,更改成自己写的管道类名
ITEM_PIPELINES = {
    'imgsPro.pipelines.imgsPipeline': 300,
}

#指定图片存储的目录
IMAGES_STORE='./imgs_lyz'

中间件

引擎和下载中间的是下载中间件 |||||重点

引擎和spider中间的是爬虫中间件

下载中间件:

​ 作用:批量拦截到到整个工程中所有的请求和响应

​ 拦截请求:

​ 1、UA伪装 process_request 2、代理IP的设定 process_exception return request

​ 拦截响应:

​ 1、篡改响应数据,相应对象

拦截请求

爬取百度模拟拦截之后使用ua伪装和ip代理进行爬取

middlewares.py

代码语言:javascript
复制
class MiddleproDownloaderMiddleware:

    user_agent_list = [
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
        "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
    ]

    PROXY_http = [
        '153.180.102.104:80',
        '195.208.131.189:56055',
    ]
    PROXY_https = [
        '120.83.49.90:9000',
        '95.189.112.214:35508',
    ]

    def process_request(self, request, spider):
        #拦截请求的
        #ua伪装
        request.headers['User-Agent']=random.choice(self.user_agent_list)
        return None

    def process_response(self, request, response, spider):
        #拦截所有的响应
        # Called with the response returned from the downloader.

        # Must either;
        # - return a Response object
        # - return a Request object
        # - or raise IgnoreRequest
        return response

    def process_exception(self, request, exception, spider):
        #拦截发生异常的请求
        #代理IP,请求被拦截之后,换一个ip进行爬取
        if request.url.split(':')[0]=='http':
            request.meta['proxy']='http://'+random.choice(self.PROXY_http)
        else:

            request.meta['proxy']='https://'+random.choice(self.PROXY_https)
        return request#将修正之后的请求对象进行重新的请求发送

settings.py

代码语言:javascript
复制
ROBOTSTXT_OBEY = False


DOWNLOADER_MIDDLEWARES = {
    'middlePro.middlewares.MiddleproDownloaderMiddleware': 543,
}

middle.py

代码语言:javascript
复制
import scrapy


class MiddleSpider(scrapy.Spider):
    #请求的拦截,爬取百度
    name = 'middle'
    #allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.baidu.com/s?wd=ip']

    def parse(self, response):
        page_txt=response.text
        with open ('ip.html','w',encoding='utf-8')as fp:
            fp.write(page_txt)
        pass

拦截响应

需求爬取网易新闻中的新闻数据(标题和内容)

1、通过网易新闻的首页解析出来五大板块对应的详情页url(没有动态加载)

2、每一个板块对应的新闻标题都是动态加载出来的(动态加载)

3、通过解析出每一个新闻详情页的url获取详情页的页面源码,解析出来新闻内容

需求:爬取网易新闻基于Scrapy爬取网易新闻中的新闻数据


wangyi.py

代码语言:javascript
复制
import scrapy
from selenium import webdriver
from wangyiPro.items import WangyiproItem

class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    allowed_domains = ['www.xxx.com']
    start_urls = ['https://news.163.com/']
    model_url_list=[]#存储五大板块对应详情页的url
    #解析五大板块对应详情页的url
    def parse(self, response):
        li_list=response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
        alist=[2,3,5,6,8]
        for index in alist:
            li=li_list[index]
            model_url=li.xpath('.//a/@href').extract_first()
            print(model_url)
            self.model_url_list.append(model_url)
        #依次对每一个板块对应的页面进行请求
        for url in self.model_url_list:
            yield scrapy.Request(url,callback=self.parse_model)
            print('第一步完成')
    #每一个板块的对应的新闻标题相关内容都是动态加载出来的
    def parse_model(self,response):
        #解析灭一个板块页面中对应的新闻的标题和新闻详情页的url
        print('第二步')
        div_list=response.xpath('/html/body/div/div[3]/div[4]/div[1]/div[1]/div/ul/li/div/div')
        for div in div_list:
            title=div.xpath('/div/div[1]/h3/a/text()').extract_first()
            new_detail_url=div.xpath('./a/@href').extract_first()
            item=WangyiproItem()
            item['title']=title
            yield scrapy.Request(url= new_detail_url, callback=self.parse_detail,meta={'item':item})
        pass


    def parse_detail(self,response):
        print('第三步')
        content=response.xpath('//*[@id="content"]/div[2]//text()').extract()
        content=''+content
        item=response.meta['item']
        item['content']=content
        yield item
        pass
    # 实例化一个浏览器对象
    def __init__(self):
        self.bro=webdriver.Chrome(executable_path='chromedriver.exe')
        pass

items.py

代码语言:javascript
复制
import scrapy


class WangyiproItem(scrapy.Item):
    # define the fields for your item here like:
    title=scrapy.Field()
    content= scrapy.Field()
    pass

middlewares.py

代码语言:javascript
复制
from itemadapter import is_item, ItemAdapter
from scrapy.http import HtmlResponse
from time import sleep


class WangyiproDownloaderMiddleware:

    def process_response(self, request, response, spider):
        #通过该方法拦截五大板块对应的响应对象,进行篡改
        #挑选出指定的响应对象进行篡改
        #spider是爬虫的对象
        bro=spider.bro#获取了爬虫类中定义的浏览器对象
        if request.url in spider.model_url_list:
            # response#五大板块对应的响应对象
            #针对定位到这些的response进行篡改
            #实例化一个新的响应对象(符合需求:包含动态加载出来的新闻数据),代替原来旧的响应对象
            #如何获取动态加载的数据
            # 基于selenium便捷的获取动态加载的数据
            bro.get(request.url)  # 五大板块对应的url进行请求发送
            sleep(5)
            page_text = bro.page_source  # 包含了动态记载的新闻数据
            new_response=HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
            return new_response
        else:
            #response#其他请求对应的响应对象
            return response

    def process_exception(self, request, exception, spider):
        pass

pipelines.py

代码语言:javascript
复制
class WangyiproPipeline:
    # 专门用来处理item类型对象
    # 该方法可以接受爬虫文件提交过来的item对象
    # 该方法没接收到一个item就会被调用一次
    def process_item(self, item, spider):
       print(item)
       return item

CrawlSpider

他就是一个基于spider的一个子类CrawlSpider;专门去做的全站数据的爬取

全站数据爬取的方式

基于spider:手动请求发送(利用页面通用的url进行页面的请求的发送)

基于CrawlSpider:

CrawlSpider的具体使用

1、创建一个工程

2、cd XXX

3、创建爬虫文件(CrawlSpider):

代码语言:javascript
复制
# 创建爬虫文件
scrapy genspider -t crawl xxx www.xxx.com

链接提取器:根据指定规则(allow=r’Items/ r’Items/‘是一个正则表达式)进行指定连接的提取,根据指定规则allow,进行连接爬取

规则解析器:将链接解析器提取到的链接进行制定规则(callback)的解析操作

找不到url链接提取去没有用没有再看

demo

代码语言:javascript
复制
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from lxml import etree

#这个就是全站爬取的demo
#5.18这个针对于个人信息,可以利用他的搜索进行查找到每一个人对应的数据,这个将大大降低我们搜索的时间和难度;针对于他的题库类型要使用全站爬取的这种方式进行爬取
class DemoproSpider(CrawlSpider):
    name = 'demoPro'
    #allowed_domains = ['www.xxx.com']
    start_urls = ['http://acm.zzuli.edu.cn/ranklist.php']
    # 实例化了一个规则解析器;
    # 三个参数所表示的意思
    # LinkExtractor链接提取器:根据指定规则(allow="正则表达式"),进行指定连接的提取
    link=LinkExtractor(allow=r'start=\d+')
    rules = (
        #规则解析器 将链接提取器提取到的链接进行制定规则(callback)的解析操作
        #链接提取器提取到的链接,callback就会执行几次
        Rule(link, callback='parse_item', follow=True),
        #follow=True; 可以将连接提取器,继续作用到链接提取器提取到的链接,所对用的页面中
        #即使有重复的url请求,我们的调度器中的过滤器,也会帮我们给过滤掉
    )

    def parse_item(self, response):#大概就是做数据分析的
        item = {}
        #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        #item['name'] = response.xpath('//div[@id="name"]').get()
        #item['description'] = response.xpath('//div[@id="description"]').get()
        print(response)
        item = {}
        page_txt = response.text
        # /html/body/div[1]/div/table/tbody
        tree = etree.HTML(page_txt)
        tr_list = tree.xpath('/html/body/div[1]/div/table/tbody/tr')
        for item in tr_list:
            userid = item.xpath('./td[2] / div / a/text()')[0]
            username = item.xpath('./td[3]/div/text()')[0]
            adad = item.xpath('./td[4]/div/a/text()')[0]
            qweqwe = item.xpath("./td[5]/div/a/text()")[0]
            bilv = item.xpath("./td[6]/div/text()")[0]
            jibie = item.xpath("./td[7]/div/text()")[0]
            #if userid == "201908064618":
            print(userid + "||" + username + "|" + adad + "||" + qweqwe + "||" + bilv + "||" + jibie)
        print(tr_list.__len__())
        return item

问题

小插曲

时间长没有做python了,又重装了系统,这爬虫这部分就一直在搁置,这打开程序发现终端识别不到scrapy程序命令。但是在pycharm确实是下载的又这个库

解决

就是在终端删除这个库,我的是他就提示这个库它本身就没有下载,然后我就先下载了一下

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 笔记
  • 图片爬取
  • 中间件
    • 拦截请求
      • 拦截响应
      • CrawlSpider
        • 全站数据爬取的方式
          • CrawlSpider的具体使用
          • 问题
            • 小插曲
            相关产品与服务
            消息队列 TDMQ
            消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档