response.xpath('//span/text').get()
response.css('span::text').get()
2.选择器使用
用Python原生方式保存
with open("movie.txt", 'wb') as f:
for n, c in zip(movie_name, movie_core):
str = n+":"+c+"\n"
f.write(str.encode())
使用Scrapy内置方式
scrapy 内置主要有四种:JSON,JSON lines,CSV,XML
最常用的导出结果格为JSON,命令如下:
scrapy crawl dmoz -o douban.json -t json
-o 后面导出文件名
-t 后面导出的类型,可以省略,但要保存的文件名后缀,写清楚类型
from itemadapter import ItemAdapter
import re
class Project06Pipeline:
def process_item(self, item, spider):
return item
from scrapy.pipelines.images import ImagesPipeline
from scrapy.http.request import Request
class MyImagePipeline(ImagesPipeline):
def get_media_requests(self, item, info):
return Request(item['image_url'])
def file_path(self, request, response=None, info=None, *, item=None):
name=item['name']
return f'{name}.jpg'
scrapy.pipelines.images.ImagesPipeline
使用 ImagesPipeline ,典型的工作流程如下所示:
image_urls
?组内(image_urls是个列表)IMAGES_STORE
import re
class Scrapy05Pipeline:
def process_item(self, item, spider):
return item
from scrapy.pipelines.images import ImagesPipeline
from scrapy.http.request import Request
class MyImagePipeline(ImagesPipeline):
def get_media_requests(self, item, info):
return Request(item['image_url'])
def file_path(self, request, response=None, info=None, *, item=None):
# 处理文件名中的特殊字符
# name = item.get('name').strip().replace('\r\n\t\t','').replace('(','').replace(')','').replace('/','_')
name = re.sub('/','_',re.sub('[\s()]','',item.get('name')))
return f'{name}.jpg'
官网-参考配置
设置 — Scrapy 2.5.0 文档 (osgeo.cn)设置 — Scrapy 2.5.0 文档
BOT_NAME
默认: 'scrapybot'
Scrapy项目实现的bot的名字。用来构造默认 User-Agent,同时也用来log。?当你使用 startproject 命令创建项目时其也被自动赋值。
CONCURRENT_ITEMS
默认: 100
Item Processor(即 Item Pipeline) 同时处理(每个response的)item的最大值
CONCURRENT_REQUESTS
默认: 16
Scrapy downloader 并发请求(concurrent requests)的最大值。
CONCURRENT_REQUESTS_PER_DOMAIN
默认: 8
对单个网站进行并发请求的最大值。
CONCURRENT_REQUESTS_PER_IP
默认: 0
对单个IP进行并发请求的最大值。如果非0,则忽略 CONCURRENT_REQUESTS_PER_DOMAIN 设定, 使用该设定。 也就是说,并发限制将针对IP,而不是网站。
该设定也影响 DOWNLOAD_DELAY: 如果 CONCURRENT_REQUESTS_PER_IP 非0,下载延迟应用在IP而不是网站上。
FEED_EXPORT_ENCODING ='utf-8'
设置导出时文件的编码
DOWNLOADER_MIDDLEWARES
默认:: {}
保存项目中启用的下载中间件及其顺序的字典
DOWNLOAD_DELAY
默认: 0
下载器在下载同一个网站下一个页面前需要等待的时间。该选项可以用来限制爬取速度, 减轻服务器压力。同时也支持小数
DOWNLOAD_TIMEOUT
默认: 180
下载器超时时间(单位: 秒)
ITEM_PIPELINES
默认: {}
保存项目中启用的pipeline及其顺序的字典。该字典默认为空,值(value)任意。 不过值(value)习惯设定在0-1000范围内
DEPTH_LIMIT
默认:0
类:scrapy.spidermiddlewares.depth.DepthMiddleware
允许为任何站点爬行的最大深度。如果为零,则不会施加任何限制。
LOG_ENABLED
默认: True
是否启用logging
LOG_ENCODING
默认: 'utf-8'
logging使用的编码。
LOG_FILE
默认: None
logging输出的文件名。如果为None,则使用标准错误输出(standard error)。
LOG_FORMAT
默认: '%(asctime)s [%(name)s] %(levelname)s: %(message)s'
日志的数据格式
LOG_DATEFORMAT
默认: '%Y-%m-%d %H:%M:%S'
日志的日期格式
LOG_LEVEL
默认: 'DEBUG'
log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG
LOG_STDOUT
默认: False
如果为 True ,进程所有的标准输出(及错误)将会被重定向到log中
ROBOTSTXT_OBEY
默认: True
是否遵循robots协议
USER_AGENT
默认: "Scrapy/VERSION (+http://scrapy.org)"
爬取的默认User-Agent,除非被覆盖
1.
scrapy startproject myfrist(project_name)
2.
scrapy genspider 爬虫名 爬虫的地址
3.spider
import scrapy
class XiaoshuoSpiderSpider(scrapy.Spider):
name = 'xiaoshuo_spider'
allowed_domains = ['zy200.com']
url = 'http://www.zy200.com/5/5943/'
start_urls = [url + '11667352.html']
def parse(self, response):
info = response.xpath("/html/body/div[@id='content']/text()").extract()
href = response.xpath("//div[@class='zfootbar']/a[3]/@href").extract_first()
yield {'content':info}
if href != 'index.html':
new_url = self.url + href
yield scrapy.Request(new_url, callback=self.parse)
4.pipline
class XiaoshuoPipeline(object):
def __init__(self):
self.filename = open("dp1.txt", "w", encoding="utf-8")
def process_item(self, item, spider):
content = item["title"] + item["content"] + '\n'
self.filename.write(content)
self.filename.flush()
return item
def close_spider(self, spider):
self.filename.close()
爬虫中请求与响应是最常见的操作,Request对象在爬虫程序中生成并传递到下载器中,后者执行请求并返回一个Response对象
class scrapy.http.Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback])
一个Request对象表示一个HTTP请求,它通常是在爬虫生成,并由下载执行,从而生成Response
参数
url(string) - 此请求的网址
callback(callable) - 将使用此请求的响应(一旦下载)作为其第一个参数调用的函数。有关更多信息,请参阅下面的将附加数据传递给回调函数。如果请求没有指定回调,parse()将使用spider的 方法。请注意,如果在处理期间引发异常,则会调用errback。
method(string) - 此请求的HTTP方法。默认为'GET'。可设置为"GET", "POST", "PUT"等,且保证字符串大写
meta(dict) - 属性的初始值Request.meta,在不同的请求之间传递数据使用
body(str或unicode) - 请求体。如果unicode传递了,那么它被编码为 str使用传递的编码(默认为utf-8)。如果 body没有给出,则存储一个空字符串。不管这个参数的类型,存储的最终值将是一个str(不会是unicode或None)。
headers(dict) - 这个请求的头。dict值可以是字符串(对于单值标头)或列表(对于多值标头)。如果 None作为值传递,则不会发送HTTP头.一般不需要
encoding: 使用默认的 'utf-8' 就行
dont_filter:是否过滤重复的URL地址,默认为?False
过滤
cookie(dict或list) - 请求cookie。这些可以以两种形式发送。
下载中间件是Scrapy请求/响应处理的钩子框架。这是一个轻、低层次的应用。
通过可下载中间件,可以处理请求之前和请求之后的数据。
每个中间件组件都是一个Python类,它定义了一个或多个以下方法,我们可能需要使用方法如下:
process_request()
process_response()
当每个request通过下载中间件时,该方法被调用
必须返回以下其中之一
返回 None
返回一个 Response 对象
返回一个 Request 对象
raise IgnoreRequest
参数:
当下载器完成http请求,传递响应给引擎的时候调用
process_response()应该是:返回一个?Response
对象,则返回一个?Request
?对象或引发?IgnoreRequest
例外情况。
如果它返回?Response
(可能是相同的给定响应,也可能是全新的响应),该响应将继续使用?process_response()
?链中的下一个中间件
如果它返回一个?Request
?对象时,中间件链将暂停,返回的请求将重新计划为将来下载。这与从返回请求的行为相同?process_request()
如果它引发了?IgnoreRequest
异常,请求的errback函数 (Request.errback
?)。如果没有代码处理引发的异常,则忽略该异常,不记录该异常(与其他异常不同)。
参数
Request
?object) -- 发起响应的请求Response
object) -- 正在处理的响应Spider
?object) -- 此响应所针对的蜘蛛class MyProxyDownloaderMiddleware:
def process_request(self, request, spider):
# request.meta['proxy'] ='http://ip:port'
# request.meta['proxy'] ='http://name:pwd@ip:port'
request.meta['proxy'] ='http://139.224.211.212:8080'
spider
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(BaiduSpider, cls).from_crawler(crawler, *args, **kwargs)
spider.chrome = webdriver.Chrome(executable_path='../tools/chromedriver.exe')
crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
# connect里的参数
# 1. 处罚事件后用哪个函数处理
# 2. 捕捉哪个事件
return spider
def spider_closed(self, spider):
spider.chrome.close()
middleware
def process_request(self, request, spider):
spider.chrome.get(request.url)
html = spider.chrome.page_source
return HtmlResponse(url = request.url,body = html,request = request,encoding='utf-8')
middleware2
# 用来创建selenium中间件
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.service import Service
from scrapy.http import HtmlResponse
class SeleniumMiddleware:
# def __init__(self):
# # 创建一个Chrome浏览器驱动
# s = Service(executable_path='scrapy07/chromedriver.exe')
# # 创建浏览器
# self.chrome = Chrome(service=s)
def process_request(self, request, spider):
# 发送请求
spider.chrome.get(request.url)
# 将数据返回到Spider中
return HtmlResponse(
url=request.url,
body=spider.chrome.page_source,
encoding='utf-8',
request=request
)
selenium
import scrapy
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.service import Service
from scrapy import signals
class SeleniumSpider(scrapy.Spider):
name = "selenium"
allowed_domains =['httpbin.org']
start_urls=['http://httpbin.org/get']
# def start_requests(self):
# #创建一个chrome浏览器驱动
# s=Service(executable_path='D:/PYthon study/auto/save-data/project08/chromedriver.exe')
# #建立浏览器
# chrome = Chrome(service=s)
# #发送请求
# chrome.get('http://httpbin.org/get')
# #获取响应
# print(chrome.page_source)
# #关闭浏览器
# chrome.quit()
# def parse(self, response):
# print(response.text)
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(SeleniumSpider, cls).from_crawler(crawler, *args, **kwargs)
#创建一个chrome浏览器驱动
s=Service(executable_path='project08\chromedriver.exe')
#建立浏览器
spider.chrome = Chrome(service=s)
crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
return spider
def spider_closed(self, spider):
#关闭浏览器
spider.chrome.quit()
def parse(self, response):
print(response.text)