首页 > 其他分享 >Scrapy-Link Extractors(链接提取器)

Scrapy-Link Extractors(链接提取器)

时间:2022-12-20 17:02:06浏览次数:54  
标签:Extractors name url scrapy 链接 item Scrapy Link response

Link Extractors 中文文档:​​https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/link-extractors.html​​​ Link Extractors 英文文档:​​http://doc.scrapy.org/en/latest/topics/link-extractors.html​

利用爬虫Scrapy中的LinkExtractor(链接提取器)爬租房信息(全站爬虫):​​https://www.jianshu.com/p/57c1e34c03cb​​ scrapy高级用法

 

 

链接提取器

 

链接提取器 的 目的 就是从 网页(scrapy.http.Response 对象中,将最终 跟随(follow) 网页(即 ​scrapy.http.Response 对象​) 的 链接 提取出来。简单的说:就是用于从服务器返回的 response 里抽取 url,用以进行之后的操作。

可以在 Scrapy 中 直接使用 ​scrapy.linkextractors import LinkExtractor  提取链接,你也可以创建自己的自定义链接提取器,以满足您的需求通过实现一个简单的界面。

每个 link extractor(链接提取器)有唯一的公共方法是 ​extract_links, ​​它 接收一个Response对象 并返回一个 ​scrapy.link.Link对象 列表。链接提取器要被实例化一次,但是它的 ​​extract_links ​​方法可以被 不同 的 网页 ​scrapy.http.Response 对象​)调用好几次,用来 提取 不同 网页中  跟随 的 链接。

Link Extractors在 ​​CrawlSpider​​​ 类( 在 Scrapy 可用 )中使用,通过一套规则,但你也可以用它在你的Spider中,即使你不是从 ​​CrawlSpider​​ 继承的子类,因为它的目的很简单:提取链接。

 

 

内置链接提取器参考

 

Scrapy 提供的 Link Extractor 类在 ​​scrapy.linkextractors​​​ 模 块提供。 默认的 link extractor 是 ​​LinkExtractor​​​ , 其实就是 ​​LxmlLinkExtractor​​:

from scrapy.linkextractors import LinkExtractor

以前的 Scrapy 版本中曾经有过其他链接提取器类,但 现在已经过时了。

 

LxmlLinkExtractor

class scrapy.linkextractors.lxmlhtml.​​LxmlLinkExtractor(allow=()deny=()allow_domains=()deny_domains=()deny_extensions=Nonerestrict_xpaths=()restrict_css=()tags=('a''area')attrs=('href')canonicalize=Falseunique=Trueprocess_value=Nonestrip=True)

LxmlLinkExtractor 是推荐的 链接提取器 与 方便的 过滤选项。它使用 lxml 的强大的 HTMLParser 实现。

参数 解释:

  • allow( 正则表达式 或 正则表达式列表 ): 一个单一的正则表达式(或正则表达式列表),(绝对)urls 必须匹配才能提取。如果没有给出(或为空),它将匹配所有链接。
  • deny( 正则表达式 或 正则表达式列表 ): 一个正则表达式(或正则表达式列表),(绝对)urls必须匹配才能排除(即不提取)。它优先于 allow 参数。如果没有给出(或为空),它不会排除任何链接。,可以 和 allow 配合一起用,前后夹击,参数和 allow 一样。
  • allow_domains( str 或 str 的 list ):允许 的 域名 或者 域名列表。即 会被提取的链接的 domains。其实这个和 spider 类里的 allowdomains 是一个作用,即 抓取哪个域名下的网站。
  • deny_domains(str 或 str 的 list ):拒绝 的 域名 或者 域名列表。即 不会被提取链接的 domains。和 allowdomains 相反,即 拒绝哪个域名下的网站。
  • deny_extensions( list ):包含在提取链接时应该忽略的扩展的单个值或字符串列表。即不允许的扩展名。如果没有给出(默认 是 None),它将默认为 IGNORED_EXTENSIONS 在 ​​scrapy.linkextractors​​​ 包中定义的 列表 。(参考: ​​http://www.xuebuyuan.com/296698.html​​)
  • restrict_xpaths( str 或 list ):一个XPath(或XPath的列表),它定义了从Response哪些区域中来提取链接。即 在网页哪个区域里提取链接,可以用 xpath 表达式和 css 表达式这个功能是划定提取链接的位置,让提取更加精准。如果给出,只有那些XPath选择的文本将被扫描链接。参见下面的例子。即 使用 xpath表达式,和allow共同作用过滤链接。
  • restrict_css( str 或 list ):一个CSS选择器(或选择器列表),用于定义响应中应提取链接的区域。同 restrict_xpaths。
  • tags( str 或 list ):提取链接时要考虑的 标签标签列表。默认为('a', 'area')。即 默认提取a标签和area标签中的链接
  • attrs( list ):在查找要提取的链接时应该考虑的属性或属性列表(仅适用于参数中指定的那些标签tags )。默认为('href',)。即 默认提取 tags 里的 href 属性,也就是 url 链接。
  • canonicalize( boolean ):规范化每个提取的url(使用 w3lib.url.canonicalize_url)。默认为True。 canonicalize each extracted url (using w3lib.url.canonicalize_url). Defaults to ​​False​​​. Note that canonicalize_url is meant for duplicate checking; it can change the URL visible at server side, so the response can be different for requests with canonicalized and raw URLs. If you’re using LinkExtractor to follow links it is more robust to keep the default ​​canonicalize=False​​.
  • unique( boolean ):是否对提取的链接进行过滤。即 这个地址是否要唯一,默认true,重复收集相同的地址没有意义。
  • process_value ( callable ) – 它接收来自扫描标签和属性提取每个值,可以修改该值,并返回一个新的,或返回 None 完全忽略链接的功能。如果没有给出,process_value 默认是 lambda x: x。其实就是:接受一个函数,可以立即对提取到的地址做加工,这个作用比较强大。比如,提取用 js 写的链接:
    例如,从这段代码中提取链接: <a href="javascript:goToPage('../other/page.html'); return false">Link text</a>你可以使用下面的这个 process_value 函数:

def process_value(value):
m = re.search("javascript:goToPage\('(.*?)'", value)
if m:
return m.group(1)

  • strip :把 提取 的 地址 前后多余的空格删除,很有必要。whether to strip whitespaces from extracted attributes. According to HTML5 standard, leading and trailing whitespaces must be stripped from ​​href​​​attributes of ​​<a>​​​, ​​<area>​​​ and many other elements, ​​src​​​ attribute of ​​<img>​​​, ​​<iframe>​​​ elements, etc., so LinkExtractor strips space chars by default. Set ​​strip=False​​ to turn it off (e.g. if you’re extracting urls from elements or attributes which allow leading/trailing whitespaces).

 

 

Spider

 

在 spider 中使用 LinkExtractor (连接提取器)

示例代码:

# -*- coding: utf-8 -*-

import scrapy
from scrapy.linkextractors import LinkExtractor


class DouBan(scrapy.Spider):
name = 'douban_spider'
allowed_domains = ['book.douban.com']
start_urls = ['https://book.douban.com/top250']

# 自定义配置。自定义配置会覆盖 setting.py 中配置,即 优先级 大于 setting.py 中配置
custom_settings = {
'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36',
}

def parse(self, response):
link_extractor = LinkExtractor(allow=(r'subject/\d+/$',), )
links = link_extractor.extract_links(response)
print(links)
for link in links:
# print(link.url, link.text)
print(link.url)


if __name__ == '__main__':
from scrapy import cmdline
cmdline.execute('scrapy crawl douban_spider'.split(' '))

 

 

CrawlSpider

 

CrawlSpider 官网文档(英文):​​http://doc.scrapy.org/en/latest/topics/spiders.html#crawlspider​​​ CrawlSpider 官网文档(中文):​​https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/spiders.html#crawlspider​

CrawlSpider 除了从 Spider类 继承过来的属性外,还提供了一个新的属性 rules 来提供跟进链接(link)的方便机制,这个机制更适合从爬取的网页中获取 link 并继续爬取的工作。

rules 包含一个或多个 Rule 对象的集合。每个 Rule 对爬取网站的动作定义了特定规则。如果多个 Rule 匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。

所以:规则的顺序可以决定获取的数据,应该把 精确匹配的规则放在前面,越模糊的规则放在后面。

CrawlSpider 也提供了一个可复写的方法:parse_start_url(response)
当 start_url 的请求返回时,该方法被调用。该方法分析最初的返回值并必须返回一个 Item 对象或一个 Request 对象或者一个可迭代的包含二者的对象

注意:当编写 CrawlSpider 爬虫 的 规则 时,不要使用 parse 作为回调函数。 由于 CrawlSpider 使用 parse 方法来实现其逻辑,如果覆盖了 parse 方法,CrawlSpider 将会运行失败。

 

 

Rule 和 Link Extractors 多用于全站的爬取

 

Rule 

爬取规则(Crawling rules)(英文):​​http://doc.scrapy.org/en/latest/topics/spiders.html#crawling-rules​​​ 爬取规则(Crawling rules)(中文):​​https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/spiders.html#crawling-rules​

更多 Scrapy rules 使用示例:​​点击打开链接​

Rule 是在定义抽取链接的规则:

class scrapy.contrib.spiders.Rule(link_extractor,callback=None,cb_kwargs=None,follow=None,process_links=None,process_request=None)

参数解释:

  1. link_extractor:是一个 Link Extractor 对象。其定义了如何从爬取到的 页面(即 response)
  2. callback:是一个 callable 或 string(该Spider中同名的函数将会被调用)。从 link_extractor 中每获取到链接时将会调用该函数。该回调函数接收一个 response 作为其第一个参数,并返回一个包含 Item 以及 Request 对象(或者这两者的子类)的列表。
  3. cb_kwargs:包含传递给回调函数的参数(keyword argument)的字典。
  4. follow:是一个 boolean 值,指定了根据该规则从 response 提取的链接 是否 需要跟进。如果 callback 为 None,follow 默认设置 True,否则默认 False。当 follow 为 True 时:爬虫会从获取的 response 中 取出符合规则的 url,再次进行爬取,如果这次爬取的 response 中还存在符合规则的 url,则再次爬取,无限循环,直到不存在符合规则的 url。 当 follow 为 False 时爬虫只从 start_urls 的 response 中取出符合规则的 url,并请求。
  5. process_links:是一个callable或string(该Spider中同名的函数将会被调用)。从link_extrator中获取到链接列表时将会调用该函数。该方法主要是用来过滤。
  6. process_request:是一个callable或string(该spider中同名的函数都将会被调用)。该规则提取到的每个request时都会调用该函数。该函数必须返回一个request或者None。用来过滤request。

 

 

豆瓣图书 top250 示例爬虫代码

 

用豆瓣图书 top250 写一个小例子。豆瓣图书 Top 250:​​https://book.douban.com/top250​

也可以使用 scrapy genspider -t crawl douban douban.com 快速创建 CrawlSpider 模板 的代码:

 

from scrapy.spiders import CrawlSpider, Rule  等价于  from scrapy.spiders.crawl import CrawlSpider, Rule

可以查看 scrapy/spiders/__init__.py ,最终导入的还是 from scrapy.spiders.crawl import CrawlSpider, Rule

Scrapy-Link Extractors(链接提取器)_html

 

创建工程:

Scrapy-Link Extractors(链接提取器)_ide_02

用 Pycharm 打开工程,可以看到生成一个 模板 爬虫:

Scrapy-Link Extractors(链接提取器)_html_03

改写模板爬虫:

# -*- coding: utf-8 -*-

from scrapy.spiders.crawl import Rule, CrawlSpider
from scrapy.linkextractors import LinkExtractor


class DouBan(CrawlSpider):
name = 'douban_spider'
allowed_domains = ['book.douban.com']
start_urls = ['https://book.douban.com/top250']

# 自定义配置。自定义配置会覆盖 setting.py 中配置,即 优先级 大于 setting.py 中配置
custom_settings = {
'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'
}

rules = (
Rule(LinkExtractor(allow=('subject/\d+/$',)), callback='parse_items'),
)

def parse_items(self, response):
print('{0} step into : parse_items(self, response)'.format(self.name))
print('current url : {0}'.format(response.url))
pass


if __name__ == '__main__':
from scrapy import cmdline
cmdline.execute('scrapy crawl douban_spider'.split(' '))

Scrapy-Link Extractors(链接提取器)_ide_04

 

运行爬虫:

  • 1. 可以直接运行 example.py 这个文件。
  • 2. 也可以在项目目录命令行运行命令:scrapy crawl douban_spider

可见爬取了很多 url,这些 url 是怎么获得的呢 ? 其实就是 Link Extractors 提取出来的。 在 rule 中定义了 LinkExtractors,LinkExtractors 接收的一个参数是 allow=(‘subject/\d+/$’,) ,是一个正则表达式。 

 

爬虫运行流程

  • 1.scrapy 请求 start_urls , 获取到 response
  • 2.使用 LinkExtractors 中 allow 的内容去匹配 response,获取到 url
  • 3.请求这个 url , 然后服务器返回的 response 交给 callback 指向的方法处理

以上是 follow 没有设置(默认为 False 的情况),在爬取到 25 个 url 的时候程序终止了。
如果将follow设置为True,将程序 中 Rule 添 一个 follow=True 参数即可。如下:

rules = (
Rule(LinkExtractor(allow=('subject/\d+/$',)),callback='parse_items',follow=True),
)

再次运行爬虫,发现爬虫(不被反爬的话)会跑很久不停下。因为在页面中有很多匹配 Rule 中正则的 URL。他们的 url 也符合规则,就会被不断的爬下来。

 

配置 logging 并 把 log  保存到文件中

可以在控制台中可以看到有很多的 log 输出。如果我们想把 log 保存到文件。可以在 setting.py 配置。

Scrapy 提供 5层 logging 级别:

  1. CRITICAL:严重错误(critical)
  2. ERROR:一般错误(regular errors)
  3. WARNING:警告信息(warning messages)
  4. INFO:一般信息(informational messages)
  5. DEBUG: 调试信息(debugging messages)

通过在 setting.py 中进行以下设置可以被用来配置 logging:

  • LOG_ENABLED 默认: True,启用logging
  • LOG_ENCODING 默认: utf-8,logging使用的编码
  • LOG_FILE 默认: None,在当前目录里创建logging输出文件的文件名
  • LOG_LEVEL 默认: DEBUG,log的最低级别
  • LOG_STDOUT 默认: False,如果为 True,进程所有的标准输出(及错误)将会被重定向到log中。例如,执行 print “hello” ,其将会在Scrapy log中显示。

在 settings.py 配置 logging

LOG_FILE = 'douban_spider.log'
LOG_LEVEL = 'DEBUG'

就可以将 log 输出到 douban_spider.log 文件中。

Scrapy-Link Extractors(链接提取器)_html_05

爬虫运行结果截图:

Scrapy-Link Extractors(链接提取器)_html_06

 

 

 

示例腾讯招聘所有页面的职位信息

 


Item 代码:

# -*- coding: utf-8 -*-

import scrapy


class TencentItem(scrapy.Item):
# define the fields for your item here like:
# 职位名
name = scrapy.Field()
# 详细链接
detailLink = scrapy.Field()
# 职位信息
positionInfo = scrapy.Field()
# 人数
peopleNumber = scrapy.Field()
# 工作地点
workLocation = scrapy.Field()
# 发布时间
publishTime = scrapy.Field()

spider 代码:

# -*- coding: utf-8 -*-
import scrapy
from douban.items import TencentItem
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class TencentSpider(CrawlSpider):
name = 'tencent'
allowed_domains = ['tencent.com']
start_urls = ['http://hr.tencent.com/position.php?&start=0#a']
rules = (
Rule(LinkExtractor(allow=r'position\.php\?&start=\d+'), callback='parse_item', follow=True),
)

def parse_item(self, response):
# i = {}
# i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
# i['name'] = response.xpath('//div[@id="name"]').extract()
# i['description'] = response.xpath('//div[@id="description"]').extract()
# return i
for each in response.xpath('//*[@class="even"]'):
name = each.xpath('./td[1]/a/text()').extract()[0]
detailLink = each.xpath('./td[1]/a/@href').extract()[0]
positionInfo = each.xpath('./td[2]/text()').extract()[0]

peopleNumber = each.xpath('./td[3]/text()').extract()[0]
workLocation = each.xpath('./td[4]/text()').extract()[0]
publishTime = each.xpath('./td[5]/text()').extract()[0]
# print name, detailLink, catalog,recruitNumber,workLocation,publishTime

item = TencentItem()
item['name'] = name
item['detailLink'] = detailLink
item['positionInfo'] = positionInfo
item['peopleNumber'] = peopleNumber
item['workLocation'] = workLocation
item['publishTime'] = publishTime

yield item


if __name__ == '__main__':
from scrapy import cmdline
cmdline.execute('scrapy crawl tencent'.split(' '))

pipeline 代码:

# -*- coding: utf-8 -*-

import json


class TencentPipeline(object):
def __init__(self):
self.filename = open("tencent.json", "w")

def process_item(self, item, spider):
text = json.dumps(dict(item), ensure_ascii=False) + ",\n"
self.filename.write(text)
return item

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

setting.py 里面启用 pipeline 配置:

ITEM_PIPELINES = {
'tencent.pipelines.TencentPipeline': 300,
}

运行爬虫,运行结果截图:

Scrapy-Link Extractors(链接提取器)_ide_07

 

 

 

使用 CrawlSpider 爬取 校花网 图片

 

校花网:​​http://www.521609.com/​

Item Pipeline 和 Spider----- 基于 scrapy 取校花网的信息 编写 item pipeline:
​​​https://cloud.tencent.com/developer/article/1098246​

上面 这个地址 是 使用 spider 爬取校花网图片,现在改用 CrawlSpider 同时有去重的功能,可以爬取多页乃至全部页面。

上面 的 下载图片是在 pipeline 中 通过 Request 请求一个 图片的URL来实现的,现在改成 通过 scrayp 自带的 图片中间件 ImagesPipeline (​​https://docs.scrapy.org/en/latest/topics/media-pipeline.html?highlight=pipeline​​)来实现图片的下载。

更多关于 ImagesPipeline

 

scrapy 的常用 ImagesPipeline 重写实现:​​https://www.jianshu.com/p/cd05763d49e8​​ 使用 Scrapy 自带的 ImagesPipeline下载图片,并对其进行分
使用 FilesPipeline ImagesPipeline:​​https://www.jianshu.com/p/a412c0277f8a​

 

item.py :

class MMItem(scrapy.Item):
image_urls = scrapy.Field()
images = scrapy.Field()
img_name = scrapy.Field()
image_paths = scrapy.Field()
pass

 

pipelines.py:

# -*- coding: utf-8 -*-

import os
from . import settings
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem


class MMPipeline(ImagesPipeline):

# def get_media_requests(self, item, info):
#
# # 这个方法是在发送下载请求之前调用的,其实这个方法本身就是去发送下载请求的
# for image_url in item['image_urls']:
# yield scrapy.Request(image_url)

def get_media_requests(self, item, info):

# 这个方法是在发送下载请求之前调用的,其实这个方法本身就是去发送下载请求的
request_objs = super(MMPipeline, self).get_media_requests(item, info)
for request_obj in request_objs:
# 向 request 对象 的 示例 动态 添加 属性
request_obj.item = item
return request_objs

def item_completed(self, results, item, info):
# 重写父类 方法
"""
所有图片处理完毕后(不管下载成功或失败),会调用item_completed进行处理
results 是一个 list 第一个为图片下载状态,
get_media_requests 在图片下载完毕后,处理结果会以二元组的方式返回给 item_completed()函数的
results,图片下载状态定义如下:
(success, image_info_or_failure)
success 表示图片是否下载成功;image_info_or_failure 是一个字典
"""
# super(MMPipeline, self).item_completed(results, item, info)
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item['image_paths'] = image_paths
return item

def file_path(self, request, respnotallow=None, info=None):
# 这个方法是在图片将要被存储的时候调用,来获取这个图片存储的路径
raw_path = super(MMPipeline, self).file_path(request, response, info)

# 'http://www.521609.com/uploads/allimg/110918/12310035925-5.jpg'
current_url = request.url

# ['http://www.521609.com/uploads/', '/110918/12310035925-5.jpg']
temp = current_url.split('allimg')

# '大庆体校张可(5)'
img_name_prefix = request.item.get('img_name')
img_name_suffix = temp[1].split('/')[-1]
category = temp[1].split('/')[-2]
image_name = img_name_prefix + img_name_suffix

image_path = os.path.join(category, image_name)
return image_path

 

mmspider.py:

# -*- coding: utf-8 -*-

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from douban.items import MMItem


class MMSpider(CrawlSpider):
name = 'xiaohua'
allowed_domains = ['www.521609.com']
start_urls = ['http://www.521609.com']
# start_urls = ['http://www.521609.com/xiaoyuanmeinv/10464_5.html']

# 自定义配置。自定义配置会覆盖 setting.py 中配置,即 优先级 大于 setting.py 中配置
custom_settings = {
'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36',
# 'LOG_FILE': 'MMSpider.log',
# 'LOG_LEVEL': 'DEBUG'
'LOG_ENABLED': False, # 关闭 scrapy 中的 debug 打印
'LOG_LEVEL': 'INFO'
}

rules = (
# 匹配 xiaohua/ 和 meinv/ 所有 URL
Rule(LinkExtractor(allow=('xiaohua/\d+_?\d+', r'meinv/\d+_?\d+')), callback='parse_img', follow=True),
Rule(LinkExtractor(allow=('xiaohua/', 'meinv/')), follow=True)
)

def parse_img(self, response):
xiaohua_name = response.xpath('//div[@class="title"]/h2/text()').extract_first()
link_extractor = LinkExtractor(
allow='uploads/allimg', # 匹配的 URL
deny='(lp\.jpg)$', # 排除的 URL。这里排除掉 以 lp.jpg 结尾 的 缩略图 URL
tags=('img', ), # 要提取链接的 标签
attrs=('src', ), # 提取的连接
restrict_xpaths='//div[@class="picbox"]', # 在 xpath 指定区域 匹配
deny_extensinotallow='' # 禁用扩展。默认会把 .jpg 扩展名的URL后缀过滤掉,这里禁用。
)
all_links = link_extractor.extract_links(response)
img_item = MMItem()
for link in all_links:
print('\t{0} : {1}'.format(xiaohua_name, link.url))

# 这里必须把 URL 放到 一个 list 里面,
# 通过查看源码可以知道 image_urls 字段 必须是一个 url 的 list
img_item['image_urls'] = [link.url, ]

img_item['img_name'] = xiaohua_name
yield img_item


if __name__ == '__main__':
from scrapy import cmdline
cmdline.execute('scrapy crawl xiaohua'.split(' '))

 

setting.py:

ROBOTSTXT_OBEY = False  # 禁用 robots.txt 

ITEM_PIPELINES = {
'xiaohua.pipelines.MMPipeline':5,
}

IMAGES_STORE = 'img_dir' # 设置图片下载路径目录

 

运行结果截图:

Scrapy-Link Extractors(链接提取器)_ide_08


 

示例代码 2:

# -*- coding: utf-8 -*-

import os
import requests
from pathlib import Path
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor


class MMSpider(CrawlSpider):
name = 'mm_spider'
allowed_domains = ['www.521609.com']
start_urls = ['http://www.521609.com']
# start_urls = ['http://www.521609.com/xiaoyuanmeinv/10464_5.html']

# 自定义配置。自定义配置会覆盖 setting.py 中配置,即 优先级 大于 setting.py 中配置
custom_settings = {
'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36',
# 'LOG_FILE': 'MMSpider.log',
# 'LOG_LEVEL': 'DEBUG'
'LOG_ENABLED': False, # 关闭 scrapy 中的 debug 打印
'LOG_LEVEL': 'INFO'
}

rules = (
# 匹配 包含 xiaohua/ 和 meinv/ 所有 URL
Rule(LinkExtractor(allow=(r'xiaohua/\d+_?\d+', r'meinv/\d+_?\d+')), callback='parse_img', follow=True),
Rule(LinkExtractor(allow=(r'xiaohua/', 'meinv/')), follow=True)
)

# def parse(self, response):
# print(response.url)
# super(MMSpider, self).parse(response)
# pass

def parse_img(self, response):
spider_name = self.name
current_url = response.url
print(f'current_url:{current_url}')

mm_name = response.xpath('//div[@class="title"]/h2/text()').extract_first()
link_extractor = LinkExtractor(
allow='uploads/allimg', # 匹配的 URL
deny=r'(lp\.jpg)$', # 排除的 URL。这里排除掉 以 lp.jpg 结尾 的 缩略图 URL
tags=('img',), # 要提取链接的 标签
attrs=('src',), # 提取的连接
restrict_xpaths='//div[@class="picbox"]', # 在 xpath 指定区域 匹配
deny_extensinotallow='' # 禁用扩展。默认会把 .jpg 扩展名的URL后缀过滤掉,这里禁用。
)
all_links = link_extractor.extract_links(response)

# 可以使用自定义的 item,也可以直接使用 Python 的 dict,
# 因为 item 本身就是一个 python类型的 dict
# img_item = MMItem()
img_item = dict()
image_urls_list = list()

for link in all_links:
print(f'\t{mm_name}:{link.url}')
image_urls_list.append(link.url)
else:
img_item['img_name'] = mm_name
img_item['image_urls'] = image_urls_list
# yield img_item
print(f'\t{img_item}')
for img_url in image_urls_list:
file_name = img_url.split('/')[-1].split('.')[0]
dir_path = f'./{mm_name}'
if not Path(dir_path).is_dir():
os.mkdir(dir_path)
file_path = f'./{mm_name}/{file_name}.jpg'
r = requests.get(url=img_url)
if 200 == r.status_code:
with open(file_path, 'wb') as f:
f.write(r.content)
else:
print(f'status_code:{r.status_code}')
pass


if __name__ == '__main__':
from scrapy import cmdline
cmdline.execute('scrapy crawl mm_spider'.split())
pass

 

 

 

 

标签:Extractors,name,url,scrapy,链接,item,Scrapy,Link,response
From: https://blog.51cto.com/csnd/5956135

相关文章

  • Scrapy源码阅读分析_1_整体框架和流程介绍
     Scrapygithub下载地址:​​https://github.com/scrapy/scrapy​​  介绍 Scrapy是一个基于Python编写的一个开源爬虫框架,它可以帮你快速、简单的方式构建爬虫,并从网站......
  • 什么情况用ArrayList or LinkedList呢?
    ArrayList和LinkedList是Java集合框架中用来存储对象引用列表的两个类。ArrayList和LinkedList都实现List接口。先对List做一个简单的了解:列表(list)是元素的有序......
  • 第四章 docker 命令部署lnmp(link方式)
    docker-cli部署DNMP(docker+nginx+mysql(MariaDB)+PHP-FPM复查完成环境部署root@docker-debian:~#mkdir-p/opt/cli-lnmp/mysqlroot@docker-debian:~#mk......
  • 最小的 x86 Linux 模拟器:blink
    1.1最小的x86Linux模拟器:blink主语言:CNewblink是一款虚拟机可用来跑静态编译的x86-64Linux,它适用于不同的操作系统和硬件架构。它和qemu-x86_64实现类似功能,除......
  • m基于simulink的WCDMA通信链路仿真
    1.算法概述W-CDMA由ETSINTTDoCoMo作为无线介面为他们的3G网路FOMA开发。后来NTTDocomo提交给ITU一个详细规范作为一个象IMT-2000一样作为一个候选的国际3G标准。国际电信......
  • m基于simulink的WCDMA通信链路仿真
    1.算法概述      W-CDMA由ETSINTTDoCoMo作为无线介面为他们的3G网路FOMA开发。后来NTTDocomo提交给ITU一个详细规范作为一个象IMT-2000一样作为一个候选的国际3G......
  • 基于瞬时功率理论的APF的SIMULINK模型仿真
    up目录一、理论基础二、核心程序三、测试结果一、理论基础由于电网中大量电力电子器件的应用,导致电网中谐波问题严重。解决电网谐波问题,首先是对电网中谐波成分的检......
  • Eolink神技之二、API全生命周期管理
    Eolink神技之二、API全生命周期管理目录​​Eolink神技之二、API全生命周期管理​​​​Eolink全API全生命周期管理解决的问题​​​​演示过程​​​​一、创建项目文档​......
  • 口全解测试-全方位了解Eolink-三神技超亮点》
    目录​​前言:​​​​神技:​​​​1、【代码生成】(★★★★★)五星推荐​​​​2、一键Swagger搬运(★★★★★)五星推荐​​​​3、eo注释与一键上传全部接口(★★★★★)五星推......
  • Flink的概念、特点及运行原理
    Flink是一个针对流数据和批数据的分布式处理引擎,主要用Java代码实现。目前,Flink主要还是依靠开源社区的贡献来发展的。对于Flink,其处理的数据主要是流数据,批数据只是流......