爬虫技术:scrapy 知识点一
---恢复内容开始---
1.scrapy框架
每一步的解释:
step1:引擎从爬虫器获取要爬行的初始请求。
step2:引擎在调度程序中调度请求,引擎把这个初始请求传递给调度器,并向调度器索要下一个请求。
step3:调度程序将下一个请求返回给引擎。
step4:引擎通过下载器中间件将请求发送给下载器。
step5:一旦页面下载完成,下载器就会生成一个响应(带有该页面)并将通过下载器中间件响应发送到引擎。
step6:引擎接收来自下载器的响应,并通过Spider中间件将其发送给Spider进行处理。
step7:爬行器处理响应,并通过爬行器中间件将抓取的数据和新请求(要跟踪的)返回给引擎
step8:引擎将处理过的数据发送到数据管道,然后将处理过的请求发送到调度程序,并请求可能的下一个要爬行的请求。
step9:流程重复(从步骤1开始),直到调度程序不再发出请求。
每一个元件的作用:
引擎 Engine:负责控制系统所有组件之间的数据流,并在某些操作发生时触发事件
调度器:调度器接收来自引擎的请求,并对它们进行排队,以便稍后在引擎请求它们时将请求对象提供给引擎。
下载器:下载器负责获取web页面并将响应内容提供给引擎,而引擎又将响应内容提供给爬虫器。
爬虫器:spider是由Scrapy用户编写的自定义类,用于解析响应并从响应或后续请求中提取数据(也称为抓取数据)。
管道:项目管道负责处理爬虫提取(或处理)后的数据。典型的任务包括清理数据、验证和持久性(比如在数据库中存储)。
下载器中间件:Downloader中间件是位于引擎和Downloader之间的特定钩子,当请求从引擎传递到Downloader以及响应从Downloader传递到引擎时,处理引擎和下载器中间的请求和响应,并进行传递。
爬虫中间件:Spider中间件是位于引擎和Spider之间的特定钩子,能够处理Spider输入(响应)和输出(数据和请求)
内容翻译于:https://doc.scrapy.org/en/master/topics/architecture.html
scrapy框架:Scrapy是用Twisted编写的,Twisted是一种流行的Python事件驱动的网络框架。因此,它使用非阻塞(即异步)代码实现并发。
Frequently Asked Questions:框架的常见问题
1.Scrapy可以使用HTTP代理吗?
是的。通过HTTP代理下载器中间件提供了对HTTP代理的支持(因为Scrapy 0.8)。具体见:HttpProxyMiddleware。
使用方式一:在中间件,middlewares.py中添加如下代码。 class ProxyMiddleware(object):
def process_request(self,request,spider):
if request.url.startswith("http://"):
request.meta['proxy']="http://"+'127.0.0.0:8000' # http代理
elif request.url.startswith("https://"):
request.meta['proxy']="https://"+'127.0.0.0:8000' # https代理 然后在setting.py中的middleware中设置
# Enable or disable downloader middlewares
# See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = { 'biquge.middlewares.ProxyMiddleware': 100,
}
使用方式二:在scarpy的爬虫代码中进行编写,重写start_request()函数,通过meta字典传递代理。 import scrapy class ProxySpider(scrapy.Spider): name = 'proxy'
allowed_domains = ["httpbin.org"] def start_requests(self): url = 'http://httpbin.org/get'
proxy = '127.0.0.0:8000' proxies = "" if url.startswith("http://"): proxies = "http://"+str(proxy) elif url.startswith("https://"): proxies = "https://"+str(proxy) #注意这里面的meta={'proxy':proxies},一定要是proxy进行携带,其它的不行,后面的proxies一定 要是字符串,其它任何形式都不行 yield scrapy.Request(url, callback=self.parse,meta={'proxy':proxies}) def parse(self,response):
print(response.text)
CrawlSpider类
rules:
它是一个(或多个)规则对象的列表。每个规则都定义了爬行站点的特定行为。规则对象描述如下。如果多个规则匹配相同的链接,则根据在此属性中定义规则的顺序使用第一个规则。有自动去重url的功能
Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
百度百科案例:深度爬取
# -*- coding: utf-8 -*-
import lxml.etree import scrapy
from scrapy.spiders import CrawlSpider,Rule #提取超链接的规则
from scrapy.linkextractors import LinkExtractor # 提取超链接
from bidubaike.items import BidubaikeItem class BaidubaikeSpider(CrawlSpider): # scrapy.Spider
name = 'baidubaike'
# 规则匹配的url样式,https://baike.baidu.com/item/%E5%A5%BD%E5%A5%BD%E8%AF%B4%E8%AF%9D/20361348?secondId=165077&mediaId=mda-hcssahwn1h3mk6zz'
# allowed_domains = ['https://baike.baidu.com/'] # 这里需要关闭这个功能
# 或者设置为下面形式
allowed_domins = ['https://baike.baidu.com/item/']
start_urls = ['https://baike.baidu.com/item/Python/407313'] # 页面提取超链接 TODO 规则定义为每一页的url,也可以实现翻页
pagelinks = LinkExtractor(allow=(r"/item/.*")) # 提取规则
# follow表示是否一致循环下去
rules = [Rule(pagelinks,callback="parse_item",follow=True)] # 返回链接的urllist # 这里不能用原生的def parse()方法,需要换一个名称,要不不能实现
def parse_item(self, response):
html = response.body.decode("utf-8")
item = BidubaikeItem()
e = lxml.etree.HTML(html)
if html != None:
title1 = e.xpath("//dd[@class='lemmaWgt-lemmaTitle-title']//h1/text()")
if len(title1) == 0:
part_a = ""
else:
part_a = title1[0]
title2 = e.xpath("//dd[@class='lemmaWgt-lemmaTitle-title']//h2/text()")
if len(title2) == 0:
part_b = ""
else:
part_b = title2[0]
title = part_a + part_b
title += "\r\n"
item["title"] = title
item["url"] = response.url
yield item else:
item["title"] = None
item["url"] = None
yield item
配置随机代理的方式:
方式一:
setting.py中设置: PROXIES = [
"http://120.84.102.21:9999",
"http://114.239.150.233:9999",
"http://112.87.71.174:9999" ]
在middleware.py中创建一个类 class ProxyMiddleWare(object): def __init__(self,ip):
self.ip = ip # 列表 @classmethod
def from_crawler(cls, crawler):
# 从setting.py中得到PORXIES列表
return cls(ip=crawler.setting.get("PORXIES")) # 列表 def process_request(self,request,spider):
ip = random.choice(self.ip) # 列表中随机选值
request.meta["proxy"] = ip # 给请求对象加上代理参数
setting.py中开启DOWNLOADER_MIDDLEWARES 并将middlewares.py中创建的类添加进去。 DOWNLOADER_MIDDLEWARES = {
'Proxy.middlewares.ProxyDownloaderMiddleware': 543,
'Proxy.middlewares.ProxyMiddleWare':543,
}
scrapy登录操作:无验证类
# -*- coding: utf-8 -*-
import scrapy class RenrenloginSpider(scrapy.Spider):
name = 'renrenlogin'
allowed_domains = ['www.renren.com']
start_urls = ['http://www.renren.com/SysHome.do'] # 人人登录界面网址 def parse(self, response):
"""表单登录,发送用户名和验证码"""
yield scrapy.FormRequest.from_response(response,
formdata={"email":"xxx","password":"xxx"}, # 这里scarpy会自动模拟js对email和passowrd进行加密
callback = self.parse_person_homepage) def parse_person_homepage(self, response):
homepage_url = "http://www.renren.com/xxx/profile"
yield scrapy.Request(url=homepage_url,callback=self.parse_user_info) def parse_user_info(self,response):
html = response.body
with open("renren.html","w") as f:
f.write(html.decode("gbk","ignore"))
scrapy登录操作:无验证类 --- 利用cookie跳转到其他页面
# -*- coding: utf-8 -*-
import scrapy class RenrenloginSpider(scrapy.Spider):
name = 'csdnlogin.py'
allowed_domains = ['www.csdn.net']
start_urls = ['https://passport.csdn.net/guide']
# 手动登录后获取到cookies,利用fidder抓取到cookies包,进行请求。
cookies = {
"uuid_tt_dd": "xxx",
"dc_session_id": "xxx",
"smidV2": "xxx",
"UN": "xxx",
"Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac": "xxx",
"Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac": "xxx",
"aliyun_webUmidToken": "xxx",
"MSG-SESSION": "xxx",
"SESSION": "xxx",
"dc_tos": "xxx",
"UserName": "xxx",
"UserInfo": "xxx",
"UserToken": "xxx",
"UserNick": "xxx",
"AU": "xxx",
"BT": "xxx",
"p_uid": "xxx",
"Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac": "xxx"
} def start_requests(self):
for url in self.start_urls:
yield scrapy.FormRequest(url=url,cookies=self.cookies,callback=self.parse_newpage) def parse_newpage(self,response):
with open("csdn.html","wb") as f:
f.write(response.body)
报错:Connection to the other side was lost in a non-clean fashion. 爬取问政的时候
构造url_list进行爬取---阳光问政
import re
import lxml.etree
import scrapy
from sun.items import SunItem class SuninfoSpider(scrapy.Spider):
name = 'suninfo'
allowed_domains = ['wz.sun0769.com']
start_urls = ['http://wz.sun0769.com/index.php/question/report?page=0'] def parse(self, response):
html_str = response.body.decode("gbk",errors="ignore")
e = lxml.etree.HTML(html_str)
count_str = e.xpath("//div[@class='pagination']/text()")[-1]
# 获取帖子数量
count = re.findall("(\d+)", count_str)[0]
page_count = int(count) // 30
url_list = list()
url = "http://wz.sun0769.com/index.php/question/report?page={}"
for i in range(0, page_count + 1):
url_list.append(url.format(i * 30))
# 测试10页的数据
for url in url_list[:10]:
yield scrapy.Request(url=url,callback=self.parse_page_info) def parse_page_info(self,response):
html_str = response.body.decode("gbk",errors="ignore")
e = lxml.etree.HTML(html_str)
item = SunItem()
tr_list = e.xpath("//div[@class='newsHead clearfix']//table[2]//tr")
for tr in tr_list:
item["id"] = tr.xpath(".//td[1]/text()")[0]
item["title"] = tr.xpath(".//td[3]//a[1]/text()")[0]
person = tr.xpath(".//td[5]/text()")
if len(person) == 0:
person = "MISS"
item["name"] = person
else:
person = tr.xpath(".//td[5]/text()")[0]
item["name"] = person
item["time"] = tr.xpath(".//td[6]/text()")[0]
yield item
自动抓取页面链接爬取---阳光问政
# -*- coding: utf-8 -*-
import re
import lxml.etree
import scrapy
from sun.items import SunItem
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor class SuninfoSpider(CrawlSpider):
name = 'suninfo'
# allowed_domains = ['wz.sun0769.com']
start_urls = ['http://wz.sun0769.com/index.php/question/report?page=0']
# http://wz.sun0769.com/index.php/question/report?page=30"
# 提取规则的正则是由Linkextractor进行设置的
pagelink = LinkExtractor(allow=(r"page=.*"))
rules = [Rule(pagelink, callback="parse_item", follow=True)] def parse_item(self, response):
html_str = response.body.decode("gbk", errors="ignore")
e = lxml.etree.HTML(html_str)
item = SunItem()
tr_list = e.xpath("//div[@class='newsHead clearfix']//table[2]//tr")
for tr in tr_list:
item["id"] = tr.xpath(".//td[1]/text()")[0]
item["title"] = tr.xpath(".//td[3]//a[1]/text()")[0]
person = tr.xpath(".//td[5]/text()")
if len(person) == 0:
person = "MISS"
item["name"] = person
else:
person = tr.xpath(".//td[5]/text()")[0]
item["name"] = person
item["time"] = tr.xpath(".//td[6]/text()")[0]
yield item
scary框架的去重原理:
第一步:框架工具包中的scrapy/utils/request.py
request_fingerprint函数---对请求对象进行签名--sha1
怎么判断请求对象是同一个呢,签名时候,对请求对象的 method,url,body(包含请求头)进行加密
请求体:request.body样子是什么呢? # TODO
sha1加密:
from hashlib import sha1
fp = sha1() str1 = "a"
str2 = "b"
str3 = "c" fp.update(str1.encode())
fp.update(str2.encode())
fp.update(str2.encode())
# 理解为:对str1 + str2 + str3 = "abc" 进行加密,因为sha1对任何长度的二进制数据加密后都得到40位的16进制字符串。
ret = fp.hexdigest() print(ret) c64d3fcde20c5cd03142171e5ac47a87aa3c8ace # 生成一个40位长度的16进制的字符串。
第二步:去重工具:scrapy/dupefilters.py
集合(防止指纹(长度为40的字符串)) set(指纹1,指纹2,指纹3,。。。。,)
request_seen---看见函数,对指纹进行处理,
指纹在集合就直接返回,不进行下一步,return True
指纹不在集合,就加入集合,再进行下一步。
第三步:scrapy/core/scheduler.py/enqueue_request 调度器
enqueue_request 函数中:request对象的 dont_fliter=false且当前request对象的签名在集合中。那么就将当前的请求对象放入请求队列中去。
具体代码分析:https://blog.csdn.net/Mr__lqy/article/details/85859361
输出log日志
settings中 LOG_FILE = "0769.log"
LOG_LEVEL = "DEBUG" 控制台不做任何输出,结果都写在名为0769的日志文件中。
scrapy抓取json数据
图片下载保存方法一:urllib.request
import urllib.request class DouyumeinvPipeline(object):
def process_item(self, item, spider):
url = item["imgurl"]
name = item["id"]
urllib.request.urlretrieve(url,"pic/{}.jpg".format(name)) # 直接使用urllib.request中的urlretrieve函数,直接将请求的资源保存指定路径
return item
图片下载保存方法二:Imagepipeline
# setting.py中设置: ITEM_PIPELINES = {
'douyuimage.pipelines.ImagePipeLine': 1,
}
# 实际上图片是全部默认保存在full文件夹中,full文件夹则保存在IMAGE_STORE这个路径下。
IMAGES_STORE = r'C:\Users\Administrator\Desktop\img'
IMAGES_EXPIRES = 90 # pipelines.py中设置: class ImagePipeLine(ImagesPipeline): def get_media_requests(self, item, info):
# 每个item都会经过这个函数,然后这个函数在发起一个请求对象,将结果传给 item_completed函数
url = item["img_url"]
yield scrapy.Request(url) def item_completed(self, results, item, info):
# results = [(True,{"path":"full/xxxxxx.jpg"})]
image_path = [x['path'] for ok, x in results if ok] # 仅仅是图片路径是:full/xxxx.jpg
if not image_path:
raise DouyuimageItem("Item contains no images")
item['image_path'] = image_path
return item # 在items中设置: class DouyuimageItem(scrapy.Item): # define the fields for your item here like:
# name = scrapy.Field()
id = scrapy.Field()
name = scrapy.Field()
img_url = scrapy.Field()
image_path = scrapy.Field()
pass # spider.py中设置: class ImgdownSpider(scrapy.Spider): name = 'imgdown'
allowed_domains = ['www.douyu.com']
current_page = 1
start_urls = ['https://www.douyu.com/gapi/rknc/directory/yzRec/{}'.format(current_page)] def parse(self, response):
item = DouyuimageItem()
data = json.loads(response.body.decode())["data"]
info_dict_list = data["rl"]
for info_dict in info_dict_list:
item["id"] = info_dict["rid"]
item["name"] = info_dict["nn"]
item["img_url"] = info_dict["rs16"]
yield item # 运行的结果
{'id': 6837192,
'image_path': ['full/e63847f2205b92e0a6c46c17d68e37f708948337.jpg'],
'img_url': 'https://rpic.douyucdn.cn/asrpic/190916/6837192_6066111_26880_2_1546.jpg',
'name': '十三金丶'}
scrapy翻页抓取数据
翻页抓取数据方式一:页码递增法
import requests
from bs4 import BeautifulSoup url = "https://blog.csdn.net/itcastcpp/article/list/1?" html_content = requests.get(url).content soup = BeautifulSoup(html_content,"html5lib") # 将网页的字节数据解析为html5的类型 div_list = soup.find_all("div",class_="article-item-box csdn-tracking-statistics") # 按照class的属性进行寻找。 for div in div_list:
title = (div.find_all("h4")[0]).find_all("a")[0]
# 获取h4下的a标签的文本值
print(title.get_text()) # 结果: 原 兄弟连区块链 Go 学习大纲-取得大纲试看视频联系微信yinchengak48 原 尹成学院golang学习快速笔记(2)表达式 原 尹成学院golang学习快速笔记(1)类型 原 区块链交易所基础开发(1)通过接口查询区块链各个币种的提币情况-ada 原 Golang精编100题-搞定golang面试
---恢复内容结束---
---恢复内容开始---
1.scrapy框架
每一步的解释:
step1:引擎从爬虫器获取要爬行的初始请求。
step2:引擎在调度程序中调度请求,引擎把这个初始请求传递给调度器,并向调度器索要下一个请求。
step3:调度程序将下一个请求返回给引擎。
step4:引擎通过下载器中间件将请求发送给下载器。
step5:一旦页面下载完成,下载器就会生成一个响应(带有该页面)并将通过下载器中间件响应发送到引擎。
step6:引擎接收来自下载器的响应,并通过Spider中间件将其发送给Spider进行处理。
step7:爬行器处理响应,并通过爬行器中间件将抓取的数据和新请求(要跟踪的)返回给引擎
step8:引擎将处理过的数据发送到数据管道,然后将处理过的请求发送到调度程序,并请求可能的下一个要爬行的请求。
step9:流程重复(从步骤1开始),直到调度程序不再发出请求。
每一个元件的作用:
引擎 Engine:负责控制系统所有组件之间的数据流,并在某些操作发生时触发事件
调度器:调度器接收来自引擎的请求,并对它们进行排队,以便稍后在引擎请求它们时将请求对象提供给引擎。
下载器:下载器负责获取web页面并将响应内容提供给引擎,而引擎又将响应内容提供给爬虫器。
爬虫器:spider是由Scrapy用户编写的自定义类,用于解析响应并从响应或后续请求中提取数据(也称为抓取数据)。
管道:项目管道负责处理爬虫提取(或处理)后的数据。典型的任务包括清理数据、验证和持久性(比如在数据库中存储)。
下载器中间件:Downloader中间件是位于引擎和Downloader之间的特定钩子,当请求从引擎传递到Downloader以及响应从Downloader传递到引擎时,处理引擎和下载器中间的请求和响应,并进行传递。
爬虫中间件:Spider中间件是位于引擎和Spider之间的特定钩子,能够处理Spider输入(响应)和输出(数据和请求)
内容翻译于:https://doc.scrapy.org/en/master/topics/architecture.html
scrapy框架:Scrapy是用Twisted编写的,Twisted是一种流行的Python事件驱动的网络框架。因此,它使用非阻塞(即异步)代码实现并发。
Frequently Asked Questions:框架的常见问题
1.Scrapy可以使用HTTP代理吗?
是的。通过HTTP代理下载器中间件提供了对HTTP代理的支持(因为Scrapy 0.8)。具体见:HttpProxyMiddleware。
使用方式一:在中间件,middlewares.py中添加如下代码。 class ProxyMiddleware(object):
def process_request(self,request,spider):
if request.url.startswith("http://"):
request.meta['proxy']="http://"+'127.0.0.0:8000' # http代理
elif request.url.startswith("https://"):
request.meta['proxy']="https://"+'127.0.0.0:8000' # https代理 然后在setting.py中的middleware中设置
# Enable or disable downloader middlewares
# See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = { 'biquge.middlewares.ProxyMiddleware': 100,
}
使用方式二:在scarpy的爬虫代码中进行编写,重写start_request()函数,通过meta字典传递代理。 import scrapy class ProxySpider(scrapy.Spider): name = 'proxy'
allowed_domains = ["httpbin.org"] def start_requests(self): url = 'http://httpbin.org/get'
proxy = '127.0.0.0:8000' proxies = "" if url.startswith("http://"): proxies = "http://"+str(proxy) elif url.startswith("https://"): proxies = "https://"+str(proxy) #注意这里面的meta={'proxy':proxies},一定要是proxy进行携带,其它的不行,后面的proxies一定 要是字符串,其它任何形式都不行 yield scrapy.Request(url, callback=self.parse,meta={'proxy':proxies}) def parse(self,response):
print(response.text)
CrawlSpider类
rules:
它是一个(或多个)规则对象的列表。每个规则都定义了爬行站点的特定行为。规则对象描述如下。如果多个规则匹配相同的链接,则根据在此属性中定义规则的顺序使用第一个规则。有自动去重url的功能
Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
百度百科案例:深度爬取
# -*- coding: utf-8 -*-
import lxml.etree import scrapy
from scrapy.spiders import CrawlSpider,Rule #提取超链接的规则
from scrapy.linkextractors import LinkExtractor # 提取超链接
from bidubaike.items import BidubaikeItem class BaidubaikeSpider(CrawlSpider): # scrapy.Spider
name = 'baidubaike'
# 规则匹配的url样式,https://baike.baidu.com/item/%E5%A5%BD%E5%A5%BD%E8%AF%B4%E8%AF%9D/20361348?secondId=165077&mediaId=mda-hcssahwn1h3mk6zz'
# allowed_domains = ['https://baike.baidu.com/'] # 这里需要关闭这个功能
# 或者设置为下面形式
allowed_domins = ['https://baike.baidu.com/item/']
start_urls = ['https://baike.baidu.com/item/Python/407313'] # 页面提取超链接 TODO 规则定义为每一页的url,也可以实现翻页
pagelinks = LinkExtractor(allow=(r"/item/.*")) # 提取规则
# follow表示是否一致循环下去
rules = [Rule(pagelinks,callback="parse_item",follow=True)] # 返回链接的urllist # 这里不能用原生的def parse()方法,需要换一个名称,要不不能实现
def parse_item(self, response):
html = response.body.decode("utf-8")
item = BidubaikeItem()
e = lxml.etree.HTML(html)
if html != None:
title1 = e.xpath("//dd[@class='lemmaWgt-lemmaTitle-title']//h1/text()")
if len(title1) == 0:
part_a = ""
else:
part_a = title1[0]
title2 = e.xpath("//dd[@class='lemmaWgt-lemmaTitle-title']//h2/text()")
if len(title2) == 0:
part_b = ""
else:
part_b = title2[0]
title = part_a + part_b
title += "\r\n"
item["title"] = title
item["url"] = response.url
yield item else:
item["title"] = None
item["url"] = None
yield item
配置随机代理的方式:
方式一:
setting.py中设置: PROXIES = [
"http://120.84.102.21:9999",
"http://114.239.150.233:9999",
"http://112.87.71.174:9999" ]
在middleware.py中创建一个类 class ProxyMiddleWare(object): def __init__(self,ip):
self.ip = ip # 列表 @classmethod
def from_crawler(cls, crawler):
# 从setting.py中得到PORXIES列表
return cls(ip=crawler.setting.get("PORXIES")) # 列表 def process_request(self,request,spider):
ip = random.choice(self.ip) # 列表中随机选值
request.meta["proxy"] = ip # 给请求对象加上代理参数
setting.py中开启DOWNLOADER_MIDDLEWARES 并将middlewares.py中创建的类添加进去。 DOWNLOADER_MIDDLEWARES = {
'Proxy.middlewares.ProxyDownloaderMiddleware': 543,
'Proxy.middlewares.ProxyMiddleWare':543,
}
scrapy登录操作:无验证类
# -*- coding: utf-8 -*-
import scrapy class RenrenloginSpider(scrapy.Spider):
name = 'renrenlogin'
allowed_domains = ['www.renren.com']
start_urls = ['http://www.renren.com/SysHome.do'] # 人人登录界面网址 def parse(self, response):
"""表单登录,发送用户名和验证码"""
yield scrapy.FormRequest.from_response(response,
formdata={"email":"xxx","password":"xxx"}, # 这里scarpy会自动模拟js对email和passowrd进行加密
callback = self.parse_person_homepage) def parse_person_homepage(self, response):
homepage_url = "http://www.renren.com/xxx/profile"
yield scrapy.Request(url=homepage_url,callback=self.parse_user_info) def parse_user_info(self,response):
html = response.body
with open("renren.html","w") as f:
f.write(html.decode("gbk","ignore"))
scrapy登录操作:无验证类 --- 利用cookie跳转到其他页面
# -*- coding: utf-8 -*-
import scrapy class RenrenloginSpider(scrapy.Spider):
name = 'csdnlogin.py'
allowed_domains = ['www.csdn.net']
start_urls = ['https://passport.csdn.net/guide']
# 手动登录后获取到cookies,利用fidder抓取到cookies包,进行请求。
cookies = {
"uuid_tt_dd": "xxx",
"dc_session_id": "xxx",
"smidV2": "xxx",
"UN": "xxx",
"Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac": "xxx",
"Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac": "xxx",
"aliyun_webUmidToken": "xxx",
"MSG-SESSION": "xxx",
"SESSION": "xxx",
"dc_tos": "xxx",
"UserName": "xxx",
"UserInfo": "xxx",
"UserToken": "xxx",
"UserNick": "xxx",
"AU": "xxx",
"BT": "xxx",
"p_uid": "xxx",
"Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac": "xxx"
} def start_requests(self):
for url in self.start_urls:
yield scrapy.FormRequest(url=url,cookies=self.cookies,callback=self.parse_newpage) def parse_newpage(self,response):
with open("csdn.html","wb") as f:
f.write(response.body)
报错:Connection to the other side was lost in a non-clean fashion. 爬取问政的时候
构造url_list进行爬取---阳光问政
import re
import lxml.etree
import scrapy
from sun.items import SunItem class SuninfoSpider(scrapy.Spider):
name = 'suninfo'
allowed_domains = ['wz.sun0769.com']
start_urls = ['http://wz.sun0769.com/index.php/question/report?page=0'] def parse(self, response):
html_str = response.body.decode("gbk",errors="ignore")
e = lxml.etree.HTML(html_str)
count_str = e.xpath("//div[@class='pagination']/text()")[-1]
# 获取帖子数量
count = re.findall("(\d+)", count_str)[0]
page_count = int(count) // 30
url_list = list()
url = "http://wz.sun0769.com/index.php/question/report?page={}"
for i in range(0, page_count + 1):
url_list.append(url.format(i * 30))
# 测试10页的数据
for url in url_list[:10]:
yield scrapy.Request(url=url,callback=self.parse_page_info) def parse_page_info(self,response):
html_str = response.body.decode("gbk",errors="ignore")
e = lxml.etree.HTML(html_str)
item = SunItem()
tr_list = e.xpath("//div[@class='newsHead clearfix']//table[2]//tr")
for tr in tr_list:
item["id"] = tr.xpath(".//td[1]/text()")[0]
item["title"] = tr.xpath(".//td[3]//a[1]/text()")[0]
person = tr.xpath(".//td[5]/text()")
if len(person) == 0:
person = "MISS"
item["name"] = person
else:
person = tr.xpath(".//td[5]/text()")[0]
item["name"] = person
item["time"] = tr.xpath(".//td[6]/text()")[0]
yield item
自动抓取页面链接爬取---阳光问政
# -*- coding: utf-8 -*-
import re
import lxml.etree
import scrapy
from sun.items import SunItem
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor class SuninfoSpider(CrawlSpider):
name = 'suninfo'
# allowed_domains = ['wz.sun0769.com']
start_urls = ['http://wz.sun0769.com/index.php/question/report?page=0']
# http://wz.sun0769.com/index.php/question/report?page=30"
# 提取规则的正则是由Linkextractor进行设置的
pagelink = LinkExtractor(allow=(r"page=.*"))
rules = [Rule(pagelink, callback="parse_item", follow=True)] def parse_item(self, response):
html_str = response.body.decode("gbk", errors="ignore")
e = lxml.etree.HTML(html_str)
item = SunItem()
tr_list = e.xpath("//div[@class='newsHead clearfix']//table[2]//tr")
for tr in tr_list:
item["id"] = tr.xpath(".//td[1]/text()")[0]
item["title"] = tr.xpath(".//td[3]//a[1]/text()")[0]
person = tr.xpath(".//td[5]/text()")
if len(person) == 0:
person = "MISS"
item["name"] = person
else:
person = tr.xpath(".//td[5]/text()")[0]
item["name"] = person
item["time"] = tr.xpath(".//td[6]/text()")[0]
yield item
scary框架的去重原理:
第一步:框架工具包中的scrapy/utils/request.py
request_fingerprint函数---对请求对象进行签名--sha1
怎么判断请求对象是同一个呢,签名时候,对请求对象的 method,url,body(包含请求头)进行加密
请求体:request.body样子是什么呢? # TODO
sha1加密:
from hashlib import sha1
fp = sha1() str1 = "a"
str2 = "b"
str3 = "c" fp.update(str1.encode())
fp.update(str2.encode())
fp.update(str2.encode())
# 理解为:对str1 + str2 + str3 = "abc" 进行加密,因为sha1对任何长度的二进制数据加密后都得到40位的16进制字符串。
ret = fp.hexdigest() print(ret) c64d3fcde20c5cd03142171e5ac47a87aa3c8ace # 生成一个40位长度的16进制的字符串。
第二步:去重工具:scrapy/dupefilters.py
集合(防止指纹(长度为40的字符串)) set(指纹1,指纹2,指纹3,。。。。,)
request_seen---看见函数,对指纹进行处理,
指纹在集合就直接返回,不进行下一步,return True
指纹不在集合,就加入集合,再进行下一步。
第三步:scrapy/core/scheduler.py/enqueue_request 调度器
enqueue_request 函数中:request对象的 dont_fliter=false且当前request对象的签名在集合中。那么就将当前的请求对象放入请求队列中去。
具体代码分析:https://blog.csdn.net/Mr__lqy/article/details/85859361
输出log日志
settings中 LOG_FILE = "0769.log"
LOG_LEVEL = "DEBUG" 控制台不做任何输出,结果都写在名为0769的日志文件中。
scrapy抓取json数据
图片下载保存方法一:urllib.request
import urllib.request class DouyumeinvPipeline(object):
def process_item(self, item, spider):
url = item["imgurl"]
name = item["id"]
urllib.request.urlretrieve(url,"pic/{}.jpg".format(name)) # 直接使用urllib.request中的urlretrieve函数,直接将请求的资源保存指定路径
return item
图片下载保存方法二:Imagepipeline
# setting.py中设置: ITEM_PIPELINES = {
'douyuimage.pipelines.ImagePipeLine': 1,
}
# 实际上图片是全部默认保存在full文件夹中,full文件夹则保存在IMAGE_STORE这个路径下。
IMAGES_STORE = r'C:\Users\Administrator\Desktop\img'
IMAGES_EXPIRES = 90 # pipelines.py中设置: class ImagePipeLine(ImagesPipeline): def get_media_requests(self, item, info):
# 每个item都会经过这个函数,然后这个函数在发起一个请求对象,将结果传给 item_completed函数
url = item["img_url"]
yield scrapy.Request(url) def item_completed(self, results, item, info):
# results = [(True,{"path":"full/xxxxxx.jpg"})]
image_path = [x['path'] for ok, x in results if ok] # 仅仅是图片路径是:full/xxxx.jpg
if not image_path:
raise DouyuimageItem("Item contains no images")
item['image_path'] = image_path
return item # 在items中设置: class DouyuimageItem(scrapy.Item): # define the fields for your item here like:
# name = scrapy.Field()
id = scrapy.Field()
name = scrapy.Field()
img_url = scrapy.Field()
image_path = scrapy.Field()
pass # spider.py中设置: class ImgdownSpider(scrapy.Spider): name = 'imgdown'
allowed_domains = ['www.douyu.com']
current_page = 1
start_urls = ['https://www.douyu.com/gapi/rknc/directory/yzRec/{}'.format(current_page)] def parse(self, response):
item = DouyuimageItem()
data = json.loads(response.body.decode())["data"]
info_dict_list = data["rl"]
for info_dict in info_dict_list:
item["id"] = info_dict["rid"]
item["name"] = info_dict["nn"]
item["img_url"] = info_dict["rs16"]
yield item # 运行的结果
{'id': 6837192,
'image_path': ['full/e63847f2205b92e0a6c46c17d68e37f708948337.jpg'],
'img_url': 'https://rpic.douyucdn.cn/asrpic/190916/6837192_6066111_26880_2_1546.jpg',
'name': '十三金丶'}
scrapy翻页抓取数据
翻页抓取数据方式一:页码递增法
import requests
from bs4 import BeautifulSoup url = "https://blog.csdn.net/itcastcpp/article/list/1?" html_content = requests.get(url).content soup = BeautifulSoup(html_content,"html5lib") # 将网页的字节数据解析为html5的类型 div_list = soup.find_all("div",class_="article-item-box csdn-tracking-statistics") # 按照class的属性进行寻找。 for div in div_list:
title = (div.find_all("h4")[0]).find_all("a")[0]
# 获取h4下的a标签的文本值
print(title.get_text()) # 结果: 原 兄弟连区块链 Go 学习大纲-取得大纲试看视频联系微信yinchengak48 原 尹成学院golang学习快速笔记(2)表达式 原 尹成学院golang学习快速笔记(1)类型 原 区块链交易所基础开发(1)通过接口查询区块链各个币种的提币情况-ada 原 Golang精编100题-搞定golang面试
scrapy中cookie的设置方法
方式一:setting中设置即可
第一步,打开setting中的DEFAULT_REQUEST_HEADER的注释
在里面添加Cookie:"xxxx"的键值对,从浏览器中复制即可
# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
"Cookie": "xxx"} 第二步,打来# COOKIES_ENABLED = False的注释,不授权使用cookie 第三步,开启爬虫
方式二:在爬虫类中重写start_requests方法
# 第一步,在spider.py中重写start_requests方法,增加cookie def start_requests(self):
url = self.start_urls[0]
cookies = {
"uuid_tt_dd":"xx",
"dc_session_id":"xx,
"smidV2":"xx",
"UN":"xx",
"Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac":"xx",
"acw_tc":"xx",
"Hm_ct_e5ef47b9f471504959267fd614d579cd":"xx",
"__yadk_uid":"xx",
"firstDie":"xx",
"UserName":"xx",
"UserInfo":"xx",
"UserToken":"xx",
"UserNick":"xx",
"BT":"xx",
"p_uid":"xx",
"Hm_lvt_e5ef47b9f471504959267fd614d579cd":"xx",
"Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac":"xx",
"acw_sc__v3":"xx",
"acw_sc__v2":"xx",
"dc_tos":"xx",
"Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac":"xx"} yield scrapy.Request(url,cookies=cookies,callback=self.parse) 第二步:保持# Disable cookies (enabled by default)的注释状态,不要打开
# COOKIES_ENABLED = False
总结:COOKIES_ENABLED = False 默认是注释的,也就是框架默认是能够使用cookie,框架默认使用的cookie需要在Scrapy.Resuest(url,cookies={})中设置。
开启 :COOKIES_ENABLED = False,此时cookie的配置需要在setting.py中的DEFAULT_REQUEST_HEADERR = {}中进行配置。
方式三:DownloadMiddleware中进行设置
第一步:setting.py中打开DOWNLOADER_MIDDLEWARES 的注释,因为设置要在这个类中进行。
DOWNLOADER_MIDDLEWARES = {
'blog.middlewares.BlogDownloaderMiddleware': 543,
} 第二步:middleware中找到对应的BlogDownloaderMiddleware,其中的函数 def process_request(self,request,spider): return None 改为: def process_request(self, request, spider): cookie_from_web = "浏览器中粘贴的Cookies:xx"
cookies = {}
for cookie in cookie_from_web.split(";"):
cookies[cookie.split('=')[0]] = cookie.split('=')[1]
print(cookies)
request.cookies = cookies
return None 第三步:
启动爬虫程序
总结:cookie的设置,都是围绕着在请求对象中加入cookie值,怎么加,在哪里加,原则就是在给解析函数返回response的那一次加就可以。
1:框架的第一次请求时,加入可以,需要重写start_request函数,请求对象参数中加入cookies={}
2. 在下载中间键,process_request函数中,给request对象加属性值,必须字典格式,request.cookies={}
3. setting.py中配置默认的请求头,在默认请求头中添加cookies。
---恢复内容结束---
爬虫技术:scrapy 知识点一的更多相关文章
- golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍
golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...
- scrapy爬虫系列之开头--scrapy知识点
介绍:Scrapy是一个为了爬取网站数据.提取结构性数据而编写的应用框架,我们只需要实现少量的代码,就能够快速抓取.Scrapy使用了Twisted异步网络框架,可以加快我们的下载速度. 0.说明: ...
- .net 爬虫技术
关于爬虫 从搜索引擎开始,爬虫应该就出现了,爬的对象当然也就是网页URL,在很长一段时间内,爬虫所做的事情就是分析URL.下载WebServer返回的HTML.分析HTML内容.构建HTTP请求的模拟 ...
- 网络爬虫框架Scrapy简介
作者: 黄进(QQ:7149101) 一. 网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本:它是一个自动提取网页的程序,它为搜索引擎从万维 ...
- 企业级Python开发大佬利用网络爬虫技术实现自动发送天气预告邮件
前天小编带大家利用Python网络爬虫采集了天气网的实时信息,今天小编带大家更进一步,将采集到的天气信息直接发送到邮箱,带大家一起嗨~~拓展来说,这个功能放在企业级角度来看,只要我们拥有客户的邮箱,之 ...
- 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http://www.xiaohuar.com/,让你体验爬取校花的成就感. Scr ...
- 爬虫之scrapy框架
解析 Scrapy解释 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓 ...
- 总结整理 -- 爬虫技术(C#版)
爬虫技术学习总结 爬虫技术 -- 基础学习(一)HTML规范化(附特殊字符编码表) 爬虫技术 -- 基本学习(二)爬虫基本认知 爬虫技术 -- 基础学习(三)理解URL和URI的联系与区别 爬虫技术 ...
- 爬虫技术 -- 基础学习(四)HtmlParser基本认识
利用爬虫技术获取网页源代码后,针对网页抽取出它的特定文本内容,利用正则表达式和抽取工具,能够更好地抽取这些内容. 下面介绍一种抽取工具 -- HtmlParser HtmlParser是一个用来解析H ...
- 【转载】教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
原文:教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神 本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http:/ ...
随机推荐
- CKEDITOR无缝粘贴word
由于工作需要必须将word文档内容粘贴到编辑器中使用 但发现word中的图片粘贴后变成了file:///xxxx.jpg这种内容,如果上传到服务器后其他人也访问不了,网上找了很多编辑器发现没有一个能直 ...
- onLayout初始化裁剪信息
在EasyConstraintLayout中初始化LayoutParamsData的paths @Override protected void onLayout(boolean changed, i ...
- 2018-2019-2 20175307 实验四《Android程序设计》实验报告
任务一 实验要求和内容: Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)>第二十 ...
- HDU4336 Card Collector (概率dp+状压dp)
http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意:有n种卡片,一个包里会包含至多一张卡片,第i种卡片在某个包中出现的次数为pi,问将所有种类的卡片集齐 ...
- Python 测评工具
开源--Python测评工具 Github仓库 本次实验作业的测评工具仅使用Python语言编写. 程序思路是基于文本的快速匹配. 编译test.py运行 1.GUI界面 GUI界面使用了PyQt5完 ...
- 用maven给SpringBoot项目打包
注意要点: 1.注意某个moule有依赖需要在对应的pom.xml里填写有关的信息,如: <dependencies> <dependency> <artifactId& ...
- .NET Core:目录
ylbtech-.NET Core:目录 1.返回顶部 1. https://dotnet.microsoft.com/ 2. 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 ...
- JavaScript-[[prototype]]的另一种理解
[[prototype]]简介 javascript 中每一个对象都会有一个特殊的内置属性[[prototype]],这个就是对其他对象对引用.有了这个作为基础去关联其他对象,就能理解继承机制.Chr ...
- 【ABAP系列】SAP ABAP模块-取整操作中CEIL和FLOOR用法
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP模块-取整操作中 ...
- Ubuntu12.04安装MariaDB并修改字符集为UTF-8
其实按照MariaDB官网的步骤来安装MariaDB特别的简单,只要按照步骤来做,很容易就搞定了. 首先,到MariaDB官网: https://downloads.mariadb.org/maria ...