为什么scrapy 递归爬取没法爬中纪委网站

匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。使用scrapy防止爬去的网站把我们的程序被ban - 简书
使用scrapy防止爬去的网站把我们的程序被ban
方法是自己写一个仿浏览器。他不可能把我们的浏览器给禁止掉吧。除了做一个浏览器还要有几个辅助的条件,cookie机制,IP代理,请求时间间隔。一想到浏览器,我天浏览器可是一个我们的工具啊,那要用多少代码给堆起来啊,一这么头就大了。可事实并非要做到浏览器那边复杂和健全,只是拿一些必不可少东西让爬去的网站认为是浏览器在访问就可以了。这里的必不可少的东西就请求中的Hesders,只要我们把该传的传过去了就可以实现欺骗了。如图:
具体实现是这样:首先创建一个.py#encoding:utf-8importrandomimportbase64fromsettingsimportPROXIESclassRandomUserAgent(object):def__init__(self, agents):self.agents = agents@classmethoddeffrom_crawler(cls,crawler):returncls(crawler.settings.getlist('USER_AGENTS'))defprocess_request(self,request,spider):print"**************************"+ random.choice(self.agents)request.headers.setdefault('User-Agent', random.choice(self.agents))classProxyMiddleware(object):defprocess_request(self,request,spider):proxy = random.choice(PROXIES)ifproxy['user_pass']is notNone:request.meta['proxy'] ="http://%s"% proxy['ip_port']encoded_user_pass = base64.encodestring(proxy['user_pass'])request.headers['Proxy-Authorization'] ='Basic '+ encoded_user_passprint"**************ProxyMiddleware havepass************"+ proxy['ip_port']print"请求头部是什么",request.headerselse:print"**************ProxyMiddleware nopass************"+ proxy['ip_port']request.meta['proxy'] ="http://%s"% proxy['ip_port']这里是代码第二步在settings.py中打开或些必要的东西添加USER_AGENTSUSER_AGENTS =["Mozilla/4.0 ( MSIE 6.0; Windows NT 5.1; SV1; AcooB .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/4.0 ( MSIE 7.0; Windows NT 6.0; Acoo B SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)","Mozilla/4.0 ( MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/5.0 (W U; MSIE 9.0; Windows NT 9.0; en-US)","Mozilla/5.0 ( MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)","Mozilla/5.0 ( MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)","Mozilla/4.0 ( MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)","Mozilla/5.0 (W U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","Mozilla/5.0 (X11; U; L en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6","Mozilla/5.0 (W U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/ K-Ninja/2.1.1","Mozilla/5.0 (W U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/ Firefox/3.0 Kapiko/3.0","Mozilla/5.0 (X11; Linux i686; U;) Gecko/ Kazehakase/0.4.5","Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11","Mozilla/5.0 (M Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20","Opera/9.80 (M Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",]添加代理IP设置PROXIESPROXIES =[{'ip_port':'111.11.228.75:80','user_pass':''},{'ip_port':'120.198.243.22:80','user_pass':''},{'ip_port':'111.8.60.9:8123','user_pass':''},{'ip_port':'101.71.27.120:80','user_pass':''},{'ip_port':'122.96.59.104:80','user_pass':''},{'ip_port':'122.224.249.122:8088','user_pass':''},]禁用cookiesCOOKIES_ENABLED=False设置下载延迟DOWNLOAD_DELAY=3添加DOWNLOADER_MIDDLEWARESDOWNLOADER_MIDDLEWARES= {'cnblogs.middlewares.RandomUserAgent':1,#随机user agent# 'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 110,'cnblogs.middlewares.ProxyMiddleware':100,#代理需要用到}添加DEFAULT_REQUEST_HEADERSDEFAULT_REQUEST_HEADERS= {'Accept':'text/html,application/xhtml+xml,application/q=0.9,*/*;q=0.8','Accept-Language':'en',}好了到这里就可以运行了。免费代理地址:/项目代码地址:/tangyi1234/cnblogs
喜欢将自己的想法转化到具体的实践中去。在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
<是个很奇怪的网站,如过你用浏览器访问时正常的,但是如果用http请求就会出现各种错。比如:wget
返回:-- 20:37:00--
()... 113.200.91.208, 42.48.109.207Connecting
()|113.200.91.208|:80... connected.HTTP request sent, awaiting response... 521
20:37:00 ERROR 521: (no description).如果用curl执行则会返回一段JS代码js也研究了下。是动态设置cookie的。一个月前整站已经被扒下来了,最近发现没有增加数据量才知道爬虫被ban了,前段时间调试的时候将浏览器的请求头全部复制到爬虫中科院正常运行,但是这两天此方法已经失效。。。请大家给我个思路,感觉瞬间没爱了!
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你的爬虫肯定被该网站检测到了,headers用了都不行那么只有看它是限制的你的ip还是账号,如果不用登录那么你先换个ip跑跑试试,看是否正常,或者直接在爬虫服务器上手动访问看能否成功
------更新-------
应题主要求,我把测试代码贴出来,这里的cookie是我刚才通过手动访问拿到的,带入它访问就没问题,至于cookie的过期时间,我没有仔细看,如果题主不懂我再好好看吧。
import requests
headers = {
'Accept': 'text/html,application/xhtml+xml,application/q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language':'zh-CN,q=0.8',
'AlexaToolbar-ALX_NS_PH': 'AlexaToolbar/alx-4.0',
'Cache-Control': 'max-age=0',
'Connection':'keep-alive',
'Host':'',
'Referer':'/',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0. Safari/537.36',
'Cookie':'__jsluid=224f8fcd6b6bd2415533; __jsl_clearance=.65|0|4opPNLlmaO6pFXwTMO%2BQ5UAhfEA%3D; JSESSIONID=AEB81C7CD16; bdshare_firstime=5'
cont = requests.get(url, headers=headers).text
print(cont)
希望对你有帮助
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神 - Python - 伯乐在线
& 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和。
Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。
Scratch,是抓取的意思,这个Python的爬虫框架叫Scrapy,大概也是这个意思吧,就叫它:小刮刮吧。
Scrapy 使用了 Twisted异步网络库来处理网络通讯。整体架构大致如下
Scrapy主要包括了以下组件:
引擎(Scrapy)
用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader)
用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
爬虫(Spiders)
爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline)
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
下载器中间件(Downloader Middlewares)
位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
爬虫中间件(Spider Middlewares)
介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
调度中间件(Scheduler Middewares)
介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。
Scrapy运行流程大概如下:
引擎从调度器中取出一个链接(URL)用于接下来的抓取
引擎把URL封装成一个请求(Request)传给下载器
下载器把资源下载下来,并封装成应答包(Response)
爬虫解析Response
解析出实体(Item),则交给实体管道进行进一步的处理
解析出的是链接(URL),则把URL交给调度器等待抓取
因为python3并不能完全支持Scrapy,因此为了完美运行Scrapy,我们使用python2.7来编写和运行Scrapy。
pip install Scrapy
pip install Scrapy
注:windows平台需要依赖pywin32,请根据自己系统32/64位选择下载安装,https://sourceforge.net/projects/pywin32/
其它可能依赖的安装包:lxml-3.6.4-cp27-cp27m-win_amd64.whl,VCForPython27.msi百度下载即可
二、基本使用
1、创建项目
scrapy startproject p1(your_project_name)
scrapy startproject p1(your_project_name)
2.自动创建目录的结果:
文件说明:
scrapy.cfg
项目的配置信息,主要为Scrapy命令行工具提供一个基础的配置信息。(真正爬虫相关的配置信息在settings.py文件中)
设置数据存储模板,用于结构化数据,如:Django的Model
数据处理行为,如:一般结构化的数据持久化
settings.py 配置文件,如:递归的层数、并发数,延迟下载等
爬虫目录,如:创建文件,编写爬虫规则
注意:一般创建爬虫文件时,以网站域名命名
3、编写爬虫
在spiders目录中新建 xiaohuar_spider.py 文件
示例代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import scrapy
class XiaoHuarSpider(scrapy.spiders.Spider):
name = "xiaohuar"
allowed_domains = [""]
start_urls = [
def parse(self, response):
# print(response, type(response))
# from scrapy.http.response.html import HtmlResponse
# print(response.body_as_unicode())
current_url = response.url #爬取时请求的url
body = response.body
#返回的html
unicode_body = response.body_as_unicode()#返回的html unicode编码
12345678910111213141516171819
#!/usr/bin/env python# -*- coding:utf-8 -*-import scrapy class XiaoHuarSpider(scrapy.spiders.Spider):&&&&name = "xiaohuar"&&&&allowed_domains = [""]&&&&start_urls = [&&&&&&&&"/hua/",&&&&] &&&&def parse(self, response):&&&&&&&&# print(response, type(response))&&&&&&&&# from scrapy.http.response.html import HtmlResponse&&&&&&&&# print(response.body_as_unicode()) &&&&&&&&current_url = response.url #爬取时请求的url&&&&&&&&body = response.body&&#返回的html&&&&&&&&unicode_body = response.body_as_unicode()#返回的html unicode编码
1.爬虫文件需要定义一个类,并继承scrapy.spiders.Spider
2.必须定义name,即爬虫名,如果没有name,会报错。因为源码中是这样定义的:
3.编写函数parse,这里需要注意的是,该函数名不能改变,因为Scrapy源码中默认callback函数的函数名就是parse;
4.定义需要爬取的url,放在列表中,因为可以爬取多个url,Scrapy源码是一个For循环,从上到下爬取这些url,使用生成器迭代将url发送给下载器下载url的html。源码截图:
进入p1目录,运行命令
scrapy crawl xiaohau --nolog
scrapy crawl xiaohau --nolog
格式:scrapy crawl+爬虫名
&#8211;nolog即不显示日志
5.scrapy查询语法:
当我们爬取大量的网页,如果自己写正则匹配,会很麻烦,也很浪费时间,令人欣慰的是,scrapy内部支持更简单的查询语法,帮助我们去html中查询我们需要的标签和标签内容以及标签属性。下面逐一进行介绍:
查询子子孙孙中的某个标签(以div标签为例)://div
查询儿子中的某个标签(以div标签为例):/div
查询标签中带有某个class属性的标签://div[@class=&#42;]即子子孙孙中标签是div且class=‘c1’的标签
查询标签中带有某个class=‘c1’并且自定义属性name=‘alex’的标签://div[@class=&#42;][@name=&#8217;alex&#8217;]
查询某个标签的文本内容://div/span/text() 即查询子子孙孙中div下面的span标签中的文本内容
查询某个属性的值(例如查询a标签的href属性)://a/@href
示例代码:
def parse(self, response):
# 分析页面
# 找到页面中符合规则的内容(校花图片),保存
# 找到所有的a标签,再访问其他a标签,一层一层的搞下去
hxs = HtmlXPathSelector(response)#创建查询对象
# 如果url是 /list-1-\d+.html
if re.match('/list-1-\d+.html', response.url): #如果url能够匹配到需要爬取的url,即本站url
items = hxs.select('//div[@class="item_list infinite_scroll"]/div') #select中填写查询目标,按scrapy查询语法书写
for i in range(len(items)):
src = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/a/img/@src' % i).extract()#查询所有img标签的src属性,即获取校花图片地址
name = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/span/text()' % i).extract() #获取span的文本内容,即校花姓名
school = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/div[@class="btns"]/a/text()' % i).extract() #校花学校
ab_src = "" + src[0]#相对路径拼接
file_name = "%s_%s.jpg" % (school[0].encode('utf-8'), name[0].encode('utf-8')) #文件名,因为python27默认编码格式是unicode编码,因此我们需要编码成utf-8
file_path = os.path.join("/Users/wupeiqi/PycharmProjects/beauty/pic", file_name)
urllib.urlretrieve(ab_src, file_path)
12345678910111213141516171819
def parse(self, response):&&&&&& # 分析页面&&&&&& # 找到页面中符合规则的内容(校花图片),保存&&&&&& # 找到所有的a标签,再访问其他a标签,一层一层的搞下去 &&&&&& hxs = HtmlXPathSelector(response)#创建查询对象 &&&&&& # 如果url是 /list-1-\d+.html&&&&&& if re.match('/list-1-\d+.html', response.url): #如果url能够匹配到需要爬取的url,即本站url&&&&&&&&&& items = hxs.select('//div[@class="item_list infinite_scroll"]/div') #select中填写查询目标,按scrapy查询语法书写&&&&&&&&&& for i in range(len(items)):&&&&&&&&&&&&&& src = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/a/img/@src' % i).extract()#查询所有img标签的src属性,即获取校花图片地址&&&&&&&&&&&&&& name = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/span/text()' % i).extract() #获取span的文本内容,即校花姓名&&&&&&&&&&&&&& school = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/div[@class="btns"]/a/text()' % i).extract() #校花学校&&&&&&&&&&&&&& if src:&&&&&&&&&&&&&&&&&& ab_src = "" + src[0]#相对路径拼接&&&&&&&&&&&&&&&&&& file_name = "%s_%s.jpg" % (school[0].encode('utf-8'), name[0].encode('utf-8')) #文件名,因为python27默认编码格式是unicode编码,因此我们需要编码成utf-8&&&&&&&&&&&&&&&&&& file_path = os.path.join("/Users/wupeiqi/PycharmProjects/beauty/pic", file_name)&&&&&&&&&&&&&&&&&& urllib.urlretrieve(ab_src, file_path)
注:urllib.urlretrieve(ab_src, file_path) ,接收文件路径和需要保存的路径,会自动去文件路径下载并保存到我们指定的本地路径。
5.递归爬取网页
上述代码仅仅实现了一个url的爬取,如果该url的爬取的内容中包含了其他url,而我们也想对其进行爬取,那么如何实现递归爬取网页呢?
示例代码:
# 获取所有的url,继续访问,并在其中寻找相同的url
all_urls = hxs.select('//a/@href').extract()
for url in all_urls:
if url.startswith('/list-1-'):
yield Request(url, callback=self.parse)
# 获取所有的url,继续访问,并在其中寻找相同的url&&&&&&&&all_urls = hxs.select('//a/@href').extract()&&&&&&&&for url in all_urls:&&&&&&&&&&&&if url.startswith('/list-1-'):&&&&&&&&&&&&&&&&yield Request(url, callback=self.parse)
即通过yield生成器向每一个url发送request请求,并执行返回函数parse,从而递归获取校花图片和校花姓名学校等信息。
注:可以修改settings.py 中的配置文件,以此来指定“递归”的层数,如: DEPTH_LIMIT = 1
6.scrapy查询语法中的正则:
from scrapy.selector import Selector
from scrapy.http import HtmlResponse
html = """&!DOCTYPE html&
&head lang="en"&
&meta charset="UTF-8"&
&title&&/title&
&li class="item-"&&a href="link.html"&first item&/a&&/li&
&li class="item-0"&&a href="link1.html"&first item&/a&&/li&
&li class="item-1"&&a href="link2.html"&second item&/a&&/li&
response = HtmlResponse(url='', body=html,encoding='utf-8')
ret = Selector(response=response).xpath('//li[re:test(@class, "item-\d*")]//@href').extract()
print(ret)
123456789101112131415161718
from scrapy.selector import Selectorfrom scrapy.http import HtmlResponsehtml = """&!DOCTYPE html&&html&&head lang="en"&&&&&&meta charset="UTF-8"&&&&&&title&&/title&&/head&&body&&&&&&li class="item-"&&a href="link.html"&first item&/a&&/li&&&&&&li class="item-0"&&a href="link1.html"&first item&/a&&/li&&&&&&li class="item-1"&&a href="link2.html"&second item&/a&&/li&&/body&&/html&"""response = HtmlResponse(url='', body=html,encoding='utf-8')ret = Selector(response=response).xpath('//li[re:test(@class, "item-\d*")]//@href').extract()print(ret)
语法规则:Selector(response=response查询对象).xpath(&#8216;//li[re:test(@class, &#8220;item-d*&#8221;)]//@href&#8217;).extract(),即根据re正则匹配,test即匹配,属性名是class,匹配的正则表达式是&#8221;item-d*&#8221;,然后获取该标签的href属性。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import scrapy
import hashlib
from tutorial.items import JinLuoSiItem
from scrapy.http import Request
from scrapy.selector import HtmlXPathSelector
class JinLuoSiSpider(scrapy.spiders.Spider):
url_set = set()
name = "jluosi"
domain = ''
allowed_domains = [""]
start_urls = [
":80/ec/goodsDetail.action?jls=QjRDNEIzMzAzOEZFNEE3NQ==",
def parse(self, response):
md5_obj = hashlib.md5()
md5_obj.update(response.url)
md5_url = md5_obj.hexdigest()
if md5_url in JinLuoSiSpider.url_set:
JinLuoSiSpider.url_set.add(md5_url)
hxs = HtmlXPathSelector(response)
if response.url.startswith(':80/ec/goodsDetail.action'):
item = JinLuoSiItem()
item['company'] = hxs.select('//div[@class="ShopAddress"]/ul/li[1]/text()').extract()
item['link'] = hxs.select('//div[@class="ShopAddress"]/ul/li[2]/text()').extract()
item['qq'] = hxs.select('//div[@class="ShopAddress"]//a/@href').re('.*uin=(?P&qq&\d*)&')
item['address'] = hxs.select('//div[@class="ShopAddress"]/ul/li[4]/text()').extract()
item['title'] = hxs.select('//h1[@class="goodsDetail_goodsName"]/text()').extract()
item['unit'] = hxs.select('//table[@class="R_WebDetail_content_tab"]//tr[1]//td[3]/text()').extract()
product_list = []
product_tr = hxs.select('//table[@class="R_WebDetail_content_tab"]//tr')
for i in range(2,len(product_tr)):
'standard':hxs.select('//table[@class="R_WebDetail_content_tab"]//tr[%d]//td[2]/text()' %i).extract()[0].strip(),
'price':hxs.select('//table[@class="R_WebDetail_content_tab"]//tr[%d]//td[3]/text()' %i).extract()[0].strip(),
product_list.append(temp)
item['product_list'] = product_list
yield item
current_page_urls = hxs.select('//a/@href').extract()
for i in range(len(current_page_urls)):
url = current_page_urls[i]
if url.startswith(''):
url_ab = url
yield Request(url_ab, callback=self.parse)
选择器规则Demo
选择器规则Demo
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
#!/usr/bin/env python# -*- coding:utf-8 -*-&import scrapyimport hashlibfrom tutorial.items import JinLuoSiItemfrom scrapy.http import Requestfrom scrapy.selector import HtmlXPathSelector&&class JinLuoSiSpider(scrapy.spiders.Spider):&&&&count = 0&&&&url_set = set()&&&&&name = "jluosi"&&&&domain = ''&&&&allowed_domains = [""]&&&&&start_urls = [&&&&&&&&":80/ec/goodsDetail.action?jls=QjRDNEIzMzAzOEZFNEE3NQ==",&&&&]&&&&&def parse(self, response):&&&&&&&&md5_obj = hashlib.md5()&&&&&&&&md5_obj.update(response.url)&&&&&&&&md5_url = md5_obj.hexdigest()&&&&&&&&if md5_url in JinLuoSiSpider.url_set:&&&&&&&&&&&&pass&&&&&&&&else:&&&&&&&&&&&&JinLuoSiSpider.url_set.add(md5_url)&&&&&&&&&&&&hxs = HtmlXPathSelector(response)&&&&&&&&&&&&if response.url.startswith(':80/ec/goodsDetail.action'):&&&&&&&&&&&&&&&&item = JinLuoSiItem()&&&&&&&&&&&&&&&&item['company'] = hxs.select('//div[@class="ShopAddress"]/ul/li[1]/text()').extract()&&&&&&&&&&&&&&&&item['link'] = hxs.select('//div[@class="ShopAddress"]/ul/li[2]/text()').extract()&&&&&&&&&&&&&&&&item['qq'] = hxs.select('//div[@class="ShopAddress"]//a/@href').re('.*uin=(?P&qq&\d*)&')&&&&&&&&&&&&&&&&item['address'] = hxs.select('//div[@class="ShopAddress"]/ul/li[4]/text()').extract()&&&&&&&&&&&&&&&&&item['title'] = hxs.select('//h1[@class="goodsDetail_goodsName"]/text()').extract()&&&&&&&&&&&&&&&&&item['unit'] = hxs.select('//table[@class="R_WebDetail_content_tab"]//tr[1]//td[3]/text()').extract()&&&&&&&&&&&&&&&&product_list = []&&&&&&&&&&&&&&&&product_tr = hxs.select('//table[@class="R_WebDetail_content_tab"]//tr')&&&&&&&&&&&&&&&&for i in range(2,len(product_tr)):&&&&&&&&&&&&&&&&&&&&temp = {&&&&&&&&&&&&&&&&&&&&&&&&'standard':hxs.select('//table[@class="R_WebDetail_content_tab"]//tr[%d]//td[2]/text()' %i).extract()[0].strip(),&&&&&&&&&&&&&&&&&&&&&&&&'price':hxs.select('//table[@class="R_WebDetail_content_tab"]//tr[%d]//td[3]/text()' %i).extract()[0].strip(),&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&product_list.append(temp)&&&&&&&&&&&&&&&&&item['product_list'] = product_list&&&&&&&&&&&&&&&&yield item&&&&&&&&&&&&&current_page_urls = hxs.select('//a/@href').extract()&&&&&&&&&&&&for i in range(len(current_page_urls)):&&&&&&&&&&&&&&&&url = current_page_urls[i]&&&&&&&&&&&&&&&&if url.startswith(''):&&&&&&&&&&&&&&&&&&&&url_ab = url&&&&&&&&&&&&&&&&&&&&yield Request(url_ab, callback=self.parse)&选择器规则Demo&选择器规则Demo
选择器规则Demo
def parse(self, response):
from scrapy.http.cookies import CookieJar
cookieJar = CookieJar()
cookieJar.extract_cookies(response, response.request)
print(cookieJar._cookies)
def parse(self, response):&&&&from scrapy.http.cookies import CookieJar&&&&cookieJar = CookieJar()&&&&cookieJar.extract_cookies(response, response.request)&&&&print(cookieJar._cookies)
获取响应cookie
更多选择器规则:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/selectors.html
7、格式化处理
上述实例只是简单的图片处理,所以在parse方法中直接处理。如果对于想要获取更多的数据(获取页面的价格、商品名称、QQ等),则可以利用Scrapy的items将数据格式化,然后统一交由pipelines来处理。即不同功能用不同文件实现。
items:即用户需要爬取哪些数据,是用来格式化数据,并告诉pipelines哪些数据需要保存。
示例items.py文件:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class JieYiCaiItem(scrapy.Item):
company = scrapy.Field()
title = scrapy.Field()
qq = scrapy.Field()
info = scrapy.Field()
more = scrapy.Field()
12345678910111213141516
# -*- coding: utf-8 -*- # Define here the models for your scraped items## See documentation in:# http://doc.scrapy.org/en/latest/topics/items.html import scrapy class JieYiCaiItem(scrapy.Item): &&&&company = scrapy.Field()&&&&title = scrapy.Field()&&&&qq = scrapy.Field()&&&&info = scrapy.Field()&&&&more = scrapy.Field()
即:需要爬取所有url中的公司名,title,qq,基本信息info,更多信息more。
上述定义模板,以后对于从请求的源码中获取的数据同样按照此结构来获取,所以在spider中需要有一下操作:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import scrapy
import hashlib
from beauty.items import JieYiCaiItem
from scrapy.http import Request
from scrapy.selector import HtmlXPathSelector
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class JieYiCaiSpider(scrapy.spiders.Spider):
url_set = set()
name = "jieyicai"
domain = ''
allowed_domains = [""]
start_urls = [
#下面是符合规则的网址,但是不抓取内容,只是提取该页的链接(这里网址是虚构的,实际使用时请替换)
#Rule(SgmlLinkExtractor(allow=(r'http://test_url/test?page_index=\d+'))),
#下面是符合规则的网址,提取内容,(这里网址是虚构的,实际使用时请替换)
#Rule(LinkExtractor(allow=(r'/Product/Detail.aspx?pid=\d+')), callback="parse"),
def parse(self, response):
md5_obj = hashlib.md5()
md5_obj.update(response.url)
md5_url = md5_obj.hexdigest()
if md5_url in JieYiCaiSpider.url_set:
JieYiCaiSpider.url_set.add(md5_url)
hxs = HtmlXPathSelector(response)
if response.url.startswith('/Product/Detail.aspx'):
item = JieYiCaiItem()
item['company'] = hxs.select('//span[@class="username g-fs-14"]/text()').extract()
item['qq'] = hxs.select('//span[@class="g-left bor1qq"]/a/@href').re('.*uin=(?P&qq&\d*)&')
item['info'] = hxs.select('//div[@class="padd20 bor1 comard"]/text()').extract()
item['more'] = hxs.select('//li[@class="style4"]/a/@href').extract()
item['title'] = hxs.select('//div[@class="g-left prodetail-text"]/h2/text()').extract()
yield item
current_page_urls = hxs.select('//a/@href').extract()
for i in range(len(current_page_urls)):
url = current_page_urls[i]
if url.startswith('/'):
url_ab = JieYiCaiSpider.domain + url
yield Request(url_ab, callback=self.parse)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
#!/usr/bin/env python# -*- coding:utf-8 -*-&import scrapyimport hashlibfrom beauty.items import JieYiCaiItemfrom scrapy.http import Requestfrom scrapy.selector import HtmlXPathSelectorfrom scrapy.spiders import CrawlSpider, Rulefrom scrapy.linkextractors import LinkExtractor&&class JieYiCaiSpider(scrapy.spiders.Spider):&&&&count = 0&&&&url_set = set()&&&&&name = "jieyicai"&&&&domain = ''&&&&allowed_domains = [""]&&&&&start_urls = [&&&&&&&&"",&&&&]&&&&&rules = [&&&&&&&&#下面是符合规则的网址,但是不抓取内容,只是提取该页的链接(这里网址是虚构的,实际使用时请替换)&&&&&&&&#Rule(SgmlLinkExtractor(allow=(r'http://test_url/test?page_index=\d+'))),&&&&&&&&#下面是符合规则的网址,提取内容,(这里网址是虚构的,实际使用时请替换)&&&&&&&&#Rule(LinkExtractor(allow=(r'/Product/Detail.aspx?pid=\d+')), callback="parse"),&&&&]&&&&&def parse(self, response):&&&&&&&&md5_obj = hashlib.md5()&&&&&&&&md5_obj.update(response.url)&&&&&&&&md5_url = md5_obj.hexdigest()&&&&&&&&if md5_url in JieYiCaiSpider.url_set:&&&&&&&&&&&&pass&&&&&&&&else:&&&&&&&&&&&&JieYiCaiSpider.url_set.add(md5_url)&&&&&&&&&&&&&&&&&&&&&&&&hxs = HtmlXPathSelector(response)&&&&&&&&&&&&if response.url.startswith('/Product/Detail.aspx'):&&&&&&&&&&&&&&&&item = JieYiCaiItem()&&&&&&&&&&&&&&&&item['company'] = hxs.select('//span[@class="username g-fs-14"]/text()').extract()&&&&&&&&&&&&&&&&item['qq'] = hxs.select('//span[@class="g-left bor1qq"]/a/@href').re('.*uin=(?P&qq&\d*)&')&&&&&&&&&&&&&&&&item['info'] = hxs.select('//div[@class="padd20 bor1 comard"]/text()').extract()&&&&&&&&&&&&&&&&item['more'] = hxs.select('//li[@class="style4"]/a/@href').extract()&&&&&&&&&&&&&&&&item['title'] = hxs.select('//div[@class="g-left prodetail-text"]/h2/text()').extract()&&&&&&&&&&&&&&&&yield item&&&&&&&&&&&&&current_page_urls = hxs.select('//a/@href').extract()&&&&&&&&&&&&for i in range(len(current_page_urls)):&&&&&&&&&&&&&&&&url = current_page_urls[i]&&&&&&&&&&&&&&&&if url.startswith('/'):&&&&&&&&&&&&&&&&&&&&url_ab = JieYiCaiSpider.domain + url&&&&&&&&&&&&&&&&&&&&yield Request(url_ab, callback=self.parse)&spider&spider
上述代码中:对url进行md5加密的目的是避免url过长,也方便保存在缓存或数据库中。
此处代码的关键在于:
将获取的数据封装在了Item对象中
yield Item对象 (一旦parse中执行yield Item对象,则自动将该对象交个pipelines的类来处理)
# -*- coding: utf-8 -*-
# Define your item pipelines here
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
import json
from twisted.enterprise import adbapi
import MySQLdb.cursors
mobile_re = re.compile(r'(13[0-9]|15[]|17[678]|18[0-9]|14[57])[0-9]{8}')
phone_re = re.compile(r'(\d+-\d+|\d+)')
class JsonPipeline(object):
def __init__(self):
self.file = open('/Users/wupeiqi/PycharmProjects/beauty/beauty/jieyicai.json', 'wb')
def process_item(self, item, spider):
line = "%s
%s\n" % (item['company'][0].encode('utf-8'), item['title'][0].encode('utf-8'))
self.file.write(line)
return item
class DBPipeline(object):
def __init__(self):
self.db_pool = adbapi.ConnectionPool('MySQLdb',
db='DbCenter',
user='root',
passwd='123',
cursorclass=MySQLdb.cursors.DictCursor,
use_unicode=True)
def process_item(self, item, spider):
query = self.db_pool.runInteraction(self._conditional_insert, item)
query.addErrback(self.handle_error)
return item
def _conditional_insert(self, tx, item):
tx.execute("select nid from company where company = %s", (item['company'][0], ))
result = tx.fetchone()
if result:
phone_obj = phone_re.search(item['info'][0].strip())
phone = phone_obj.group() if phone_obj else ' '
mobile_obj = mobile_re.search(item['info'][1].strip())
mobile = mobile_obj.group() if mobile_obj else ' '
values = (
item['company'][0],
item['qq'][0],
item['info'][2].strip(),
item['more'][0])
tx.execute("insert into company(company,qq,phone,mobile,address,more) values(%s,%s,%s,%s,%s,%s)", values)
def handle_error(self, e):
print 'error',e
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
# -*- coding: utf-8 -*-&# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html&import jsonfrom twisted.enterprise import adbapiimport MySQLdb.cursorsimport re&mobile_re = re.compile(r'(13[0-9]|15[]|17[678]|18[0-9]|14[57])[0-9]{8}')phone_re = re.compile(r'(\d+-\d+|\d+)')&class JsonPipeline(object):&&&&&def __init__(self):&&&&&&&&self.file = open('/Users/wupeiqi/PycharmProjects/beauty/beauty/jieyicai.json', 'wb')&&&&&&def process_item(self, item, spider):&&&&&&&&line = "%s&&%s\n" % (item['company'][0].encode('utf-8'), item['title'][0].encode('utf-8'))&&&&&&&&self.file.write(line)&&&&&&&&return item&class DBPipeline(object):&&&&&def __init__(self):&&&&&&&&self.db_pool = adbapi.ConnectionPool('MySQLdb',&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& db='DbCenter',&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& user='root',&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& passwd='123',&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& cursorclass=MySQLdb.cursors.DictCursor,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& use_unicode=True)&&&&&def process_item(self, item, spider):&&&&&&&&query = self.db_pool.runInteraction(self._conditional_insert, item)&&&&&&&&query.addErrback(self.handle_error)&&&&&&&&return item&&&&&def _conditional_insert(self, tx, item):&&&&&&&&tx.execute("select nid from company where company = %s", (item['company'][0], ))&&&&&&&&result = tx.fetchone()&&&&&&&&if result:&&&&&&&&&&&&pass&&&&&&&&else:&&&&&&&&&&&&phone_obj = phone_re.search(item['info'][0].strip())&&&&&&&&&&&&phone = phone_obj.group() if phone_obj else ' '&&&&&&&&&&&&&mobile_obj = mobile_re.search(item['info'][1].strip())&&&&&&&&&&&&mobile = mobile_obj.group() if mobile_obj else ' '&&&&&&&&&&&&&values = (&&&&&&&&&&&&&&&&item['company'][0],&&&&&&&&&&&&&&&&item['qq'][0],&&&&&&&&&&&&&&&&phone,&&&&&&&&&&&&&&&&mobile,&&&&&&&&&&&&&&&&item['info'][2].strip(),&&&&&&&&&&&&&&&&item['more'][0])&&&&&&&&&&&&tx.execute("insert into company(company,qq,phone,mobile,address,more) values(%s,%s,%s,%s,%s,%s)", values)&&&&&def handle_error(self, e):&&&&&&&&print 'error',e&pipelines&pipelines
上述代码中多个类的目的是,可以同时保存在文件和数据库中,保存的优先级可以在配置文件settings中定义。
ITEM_PIPELINES = {
'beauty.pipelines.DBPipeline': 300,
'beauty.pipelines.JsonPipeline': 100,
# 每行后面的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内。
ITEM_PIPELINES = {&&&&'beauty.pipelines.DBPipeline': 300,&&&&'beauty.pipelines.JsonPipeline': 100,}# 每行后面的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内。
总结:本文对python爬虫框架Scrapy做了详细分析和实例讲解,如果本文对您有参考价值,欢迎帮博主点下文章下方的推荐,谢谢!
可能感兴趣的话题
o 256 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
&#8211; 好的话题、有启发的回复、值得信赖的圈子
&#8211; 分享和发现有价值的内容与观点
&#8211; 为IT单身男女服务的征婚传播平台
&#8211; 优秀的工具资源导航
&#8211; 翻译传播优秀的外文文章
&#8211; 国内外的精选文章
&#8211; UI,网页,交互和用户体验
&#8211; 专注iOS技术分享
&#8211; 专注Android技术分享
&#8211; JavaScript, HTML5, CSS
&#8211; 专注Java技术分享
&#8211; 专注Python技术分享
& 2017 伯乐在线

我要回帖

更多关于 scrapy 爬取多个网站 的文章

 

随机推荐