---恢复内容开始---

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_extractorcallback=Nonecb_kwargs=Nonefollow=Noneprocess_links=Noneprocess_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_extractorcallback=Nonecb_kwargs=Nonefollow=Noneprocess_links=Noneprocess_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 知识点一的更多相关文章

  1. golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍

    golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...

  2. scrapy爬虫系列之开头--scrapy知识点

    介绍:Scrapy是一个为了爬取网站数据.提取结构性数据而编写的应用框架,我们只需要实现少量的代码,就能够快速抓取.Scrapy使用了Twisted异步网络框架,可以加快我们的下载速度. 0.说明: ...

  3. .net 爬虫技术

    关于爬虫 从搜索引擎开始,爬虫应该就出现了,爬的对象当然也就是网页URL,在很长一段时间内,爬虫所做的事情就是分析URL.下载WebServer返回的HTML.分析HTML内容.构建HTTP请求的模拟 ...

  4. 网络爬虫框架Scrapy简介

    作者: 黄进(QQ:7149101) 一. 网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本:它是一个自动提取网页的程序,它为搜索引擎从万维 ...

  5. 企业级Python开发大佬利用网络爬虫技术实现自动发送天气预告邮件

    前天小编带大家利用Python网络爬虫采集了天气网的实时信息,今天小编带大家更进一步,将采集到的天气信息直接发送到邮箱,带大家一起嗨~~拓展来说,这个功能放在企业级角度来看,只要我们拥有客户的邮箱,之 ...

  6. 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神

    本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http://www.xiaohuar.com/,让你体验爬取校花的成就感. Scr ...

  7. 爬虫之scrapy框架

    解析 Scrapy解释 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓 ...

  8. 总结整理 -- 爬虫技术(C#版)

    爬虫技术学习总结 爬虫技术 -- 基础学习(一)HTML规范化(附特殊字符编码表) 爬虫技术 -- 基本学习(二)爬虫基本认知 爬虫技术 -- 基础学习(三)理解URL和URI的联系与区别 爬虫技术 ...

  9. 爬虫技术 -- 基础学习(四)HtmlParser基本认识

    利用爬虫技术获取网页源代码后,针对网页抽取出它的特定文本内容,利用正则表达式和抽取工具,能够更好地抽取这些内容. 下面介绍一种抽取工具 -- HtmlParser HtmlParser是一个用来解析H ...

  10. 【转载】教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神

    原文:教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神 本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http:/ ...

随机推荐

  1. CKEDITOR无缝粘贴word

    由于工作需要必须将word文档内容粘贴到编辑器中使用 但发现word中的图片粘贴后变成了file:///xxxx.jpg这种内容,如果上传到服务器后其他人也访问不了,网上找了很多编辑器发现没有一个能直 ...

  2. onLayout初始化裁剪信息

    在EasyConstraintLayout中初始化LayoutParamsData的paths @Override protected void onLayout(boolean changed, i ...

  3. 2018-2019-2 20175307 实验四《Android程序设计》实验报告

    任务一 实验要求和内容: Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)>第二十 ...

  4. HDU4336 Card Collector (概率dp+状压dp)

    http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意:有n种卡片,一个包里会包含至多一张卡片,第i种卡片在某个包中出现的次数为pi,问将所有种类的卡片集齐 ...

  5. Python 测评工具

    开源--Python测评工具 Github仓库 本次实验作业的测评工具仅使用Python语言编写. 程序思路是基于文本的快速匹配. 编译test.py运行 1.GUI界面 GUI界面使用了PyQt5完 ...

  6. 用maven给SpringBoot项目打包

    注意要点: 1.注意某个moule有依赖需要在对应的pom.xml里填写有关的信息,如: <dependencies> <dependency> <artifactId& ...

  7. .NET Core:目录

    ylbtech-.NET Core:目录 1.返回顶部 1. https://dotnet.microsoft.com/ 2. 2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部   ...

  8. JavaScript-[[prototype]]的另一种理解

    [[prototype]]简介 javascript 中每一个对象都会有一个特殊的内置属性[[prototype]],这个就是对其他对象对引用.有了这个作为基础去关联其他对象,就能理解继承机制.Chr ...

  9. 【ABAP系列】SAP ABAP模块-取整操作中CEIL和FLOOR用法

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP模块-取整操作中 ...

  10. Ubuntu12.04安装MariaDB并修改字符集为UTF-8

    其实按照MariaDB官网的步骤来安装MariaDB特别的简单,只要按照步骤来做,很容易就搞定了. 首先,到MariaDB官网: https://downloads.mariadb.org/maria ...