关于scrapy:2022新版Scrapy打造搜索引擎-畅销4年的Python分布式爬虫箪瓢自钟鼎

download:2022新版Scrapy打造搜索引擎 滞销4年的Python分布式爬虫WEB前端技术:从HTML、CSS到JavaScript的全面介绍随着互联网的遍及和倒退,WEB前端技术也变得越来越重要。本文将全面介绍WEB前端技术,包含HTML、CSS和JavaScript三方面的内容。 HTMLHTML(Hypertext Markup Language)是一种用于创立网页的标记语言。它通过各种标签和属性来形容网页上的内容和构造。HTML标签通常由尖括号突围,例如<html>、<head>、<body>等。HTML还反对链接、图片、表格、表单等性能,这些都是通过不同的标签和属性实现的。 CSSCSS(Cascading Style Sheets)是一种用于管制网页外观的样式表语言。它能够扭转文本的色彩、字体、大小,设置页面布局和款式等。CSS通过层叠规定来确定利用哪个款式,同时也反对选择器来抉择元素并为其利用款式。CSS还反对动画和转换等高级成果,能够让网页更加丰富多彩。 JavaScriptJavaScript是一种广泛应用于WEB前端开发的编程语言,它能够在网页中增加动态效果、交互行为、数据验证和操作等。JavaScript能够通过DOM(Document Object Model)和BOM(Browser Object Model)来拜访和管制网页元素。它还能够通过AJAX(Asynchronous JavaScript and XML)技术实现异步数据交互,使网页更加晦涩和疾速。 总之,WEB前端技术是创立网页和应用程序的关键所在。HTML、CSS和JavaScript三者相辅相成,独特构建了一个残缺的网页。通过学习WEB前端技术,开发者能够创立出高质量、高性能的网站和应用程序。

May 11, 2023 · 1 min · jiezi

关于scrapy:POST传参方式的说明及scrapy和requests实现

1、application/x-www-form-urlencoded如果不设置Content-type,默认为该形式,提交的数据依照 key1=val1&key2=val2 的形式进行编码。 requests :scrapy: 2、application/json:申请所需参数以json的数据格式写入body中,后盾也以json格局进行解析。 requests: scrapy:3、multipart/form-data:用于上传表单位文件。 4、text/xml:当初根本不必( 因为XML 构造过于臃肿,个别场景用 JSON 会更灵便不便)。

November 9, 2022 · 1 min · jiezi

关于scrapy:新版Scrapy打造搜索引擎-畅销4年的Python分布式爬虫课2022

download:新版Scrapy打造搜索引擎 滞销4年的Python分布式爬虫课2022单例模式的简介咱们将一个类在当行过程中只有一个实例的这种模式,称之为“单例模式”那么Java代码如何实现一个单例模式呢?下文将一一到来,如下所示: 单例模式的注意事项: 1.单例模式在一个过程中只有一个实例 2.单例类通常由自己创建自身的实例 3.单例类给其余对象提供的都是同一个实例1.2.3.4.测试代码 package com.java265.Singleton;public class Test { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("------单例模式-----"); //创建100个线程进行测试 for(int i=0;i<100;i++) { new Thread(()->{ System.out.println(Single01.getInstance()); }).start(); }}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16. 单例实现模式1饿汉式单例模式:间接使用一个动态变量,在JVM加载类时,生成一个单例实例 如下 package com.java265.Singleton; public class Single01 { private static final Single01 INSTANCE = new Single01();private Single01() {}public static Single01 getInstance () { return INSTANCE;}}1.2.3.4.5.6.7.8.9.10.11. 使用static动态代码块生成一个单例类 package com.java265.Singleton;public class Single02 { private static final Single02 INSTANCE;static { INSTANCE = new Single02();}private Single02() {}public static Single02 getInstance() { return INSTANCE; }public void t() { System.out.println("Single02 t方法" + "");}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18. ...

October 6, 2022 · 1 min · jiezi

关于scrapy:Scrapy介绍及入门

一、Scrapy简介 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的利用框架。 能够利用在包含数据挖掘,信息处理或存储历史数据等一系列的程序中。 其最后是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也能够利用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。 二、架构概览1. Scrapy Engine 引擎负责管制数据流在零碎中所有组件中流动,并在相应动作产生时触发事件。 具体内容查看上面的数据流(Data Flow)局部。此组件相当于爬虫的“大脑”,是整个爬虫的调度核心。 2. 调度器(Scheduler) 调度器从引擎承受request并将他们入队,以便之后引擎申请他们时提供给引擎。 初始的爬取URL和后续在页面中获取的待爬取的URL将放入调度器中,期待爬取。同时调度器会主动去除反复的URL(如果特定的URL不须要去重也能够通过设置实现,如post申请的URL)3. 下载器(Downloader) 下载器负责获取页面数据并提供给引擎,而后提供给spider。4. Spiders Spider是Scrapy用户编写用于剖析response并提取item(即获取到的item)或额定跟进的URL的类。 每个spider负责解决一个特定(或一些)网站。5. Item Pipeline Item Pipeline负责解决被spider提取进去的item。典型的解决有清理、 验证及长久化(例如存取到数据库中)。 当页面被爬虫解析所需的数据存入Item后,将被发送到我的项目管道(Pipeline),并通过几个特定的秩序解决数据,最初存入本地文件或存入数据库。6. 下载器中间件(Downloader middlewares) 下载器中间件是在引擎及下载器之间的特定钩子(specific hook),解决Downloader传递给引擎的response。 其提供了一个简便的机制,通过插入自定义代码来扩大Scrapy性能。通过设置下载器中间件能够实现爬虫主动更换user-agent、IP等性能。7. Spider中间件(Spider middlewares) Spider中间件是在引擎及Spider之间的特定钩子(specific hook),解决spider的输出(response)和输入(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩大Scrapy性能。8. 数据流(Data flow) 1) 引擎关上一个网站(open a domain),找到解决该网站的Spider并向该spider申请第一个要爬取的URL(s)。 2) 引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)以Request调度。 3) 引擎向调度器申请下一个要爬取的URL。 4) 调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(申请(request)方向)转发给下载器(Downloader)。 5) 一旦页面下载结束,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方向)发送给引擎。 6) 引擎从下载器中接管到Response并通过Spider中间件(输出方向)发送给Spider解决。 7) Spider解决Response并返回爬取到的Item及(跟进的)新的Request给引擎。 8) 引擎将(Spider返回的)爬取到的Item给Item Pipeline,将(Spider返回的)Request给调度器。 9) (从第二步)反复直到调度器中没有更多地request,引擎敞开该网站。 ...

September 6, 2021 · 2 min · jiezi

关于scrapy:36利用开源的scrapyredis编写分布式爬虫代码

【百度云搜寻,搜各种材料:http://www.lqkweb.com】【搜网盘,搜各种材料:http://www.swpan.cn】scrapy-redis是一个能够scrapy联合redis搭建分布式爬虫的开源模块 scrapy-redis的依赖 Python 2.7, 3.4 or 3.5,Python反对版本Redis >= 2.8,Redis版本Scrapy >= 1.1,Scrapy版本redis-py >= 2.10,redis-py版本,redis-py是一个Python操作Redis的模块,scrapy-redis底层是用redis-py来实现的``下载地址:https://pypi.python.org/pypi/... 咱们以scrapy-redis/0.6.8版本为讲 一、装置scrapy-redis/0.6.8版本的依赖 首先装置好scrapy-redis/0.6.8版本的依赖关系模块和软件 二、创立scrapy我的项目 执行命令创立我的项目:scrapy startproject fbshpch 三、将下载的scrapy-redis-0.6.8模块包解压,解压后将包里的crapy-redis-0.6.8\src\scrapy_redis的scrapy_redis文件夹复制到我的项目中 四、分布式爬虫实现代码,一般爬虫,相当于basic命令创立的一般爬虫 留神:分布式一般爬虫必须继承scrapy-redis的RedisSpider类 #!/usr/bin/env python# -*- coding:utf8 -*-from scrapy_redis.spiders import RedisSpider    # 导入scrapy_redis里的RedisSpider类import scrapyfrom scrapy.http import Request                 #导入url返回给下载器的办法from urllib import parse                        #导入urllib库里的parse模块class jobboleSpider(RedisSpider):               # 自定义爬虫类,继承RedisSpider类    name = 'jobbole'                            # 设置爬虫名称    allowed_domains = ['blog.jobbole.com']       # 爬取域名    redis_key = 'jobbole:start_urls'            # 向redis设置一个名称贮存url    def parse(self, response):        """        获取列表页的文章url地址,交给下载器        """        # 获取当前页文章url        lb_url = response.xpath('//a[@class="archive-title"]/@href').extract()  # 获取文章列表url        for i in lb_url:            # print(parse.urljoin(response.url,i))                                             #urllib库里的parse模块的urljoin()办法,是主动url拼接,如果第二个参数的url地址是相对路径会主动与第一个参数拼接            yield Request(url=parse.urljoin(response.url, i),                          callback=self.parse_wzhang)  # 将循环到的文章url增加给下载器,下载后交给parse_wzhang回调函数        # 获取下一页列表url,交给下载器,返回给parse函数循环        x_lb_url = response.xpath('//a[@class="next page-numbers"]/@href').extract()  # 获取下一页文章列表url        if x_lb_url:            yield Request(url=parse.urljoin(response.url, x_lb_url[0]),                          callback=self.parse)  # 获取到下一页url返回给下载器,回调给parse函数循环进行    def parse_wzhang(self, response):        title = response.xpath('//div[@class="entry-header"]/h1/text()').extract()  # 获取文章题目        print(title)五、分布式爬虫实现代码,全站主动爬虫,相当于crawl命令创立的全站主动爬虫 留神:分布式全站主动爬虫必须继承scrapy-redis的RedisCrawlSpider类 #!/usr/bin/env python# -*- coding:utf8 -*-from scrapy_redis.spiders import RedisCrawlSpider    # 导入scrapy_redis里的RedisCrawlSpider类import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import Ruleclass jobboleSpider(RedisCrawlSpider):               # 自定义爬虫类,继承RedisSpider类    name = 'jobbole'                                 # 设置爬虫名称    allowed_domains = ['www.luyin.org']              # 爬取域名    redis_key = 'jobbole:start_urls'                 # 向redis设置一个名称贮存url    rules = (        # 配置抓取列表页规定        # Rule(LinkExtractor(allow=('ggwa/.*')), follow=True),        # 配置抓取内容页规定        Rule(LinkExtractor(allow=('.*')), callback='parse_job', follow=True),    )    def parse_job(self, response):  # 回调函数,留神:因为CrawlS模板的源码创立了parse回调函数,所以切记咱们不能创立parse名称的函数        # 利用ItemLoader类,加载items容器类填充数据        neir = response.css('title::text').extract()        print(neir)六、settings.py文件配置 # 分布式爬虫设置SCHEDULER = "scrapy_redis.scheduler.Scheduler"                  # 使调度在redis存储申请队列DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"      # 确保所有的蜘蛛都共享雷同的过滤器通过Redis复制ITEM_PIPELINES = {    'scrapy_redis.pipelines.RedisPipeline': 300                 # 存储在redis刮项后处理}七、执行分布式爬虫 1、运行命令:scrapy crawl jobbole(jobbole示意爬虫名称) 2、启动redis,而后cd到redis的装置目录, 执行命令:redis-cli -h 127.0.0.1 -p 6379  连贯一个redis客户端 在连贯客户端执行命令:lpush jobbole:start_urls http://blog.jobbole.com/all-p...  ,向redis列队创立一个起始URL 阐明:lpush(列表数据) jobbole:start_urls(爬虫里定义的url列队名称) http://blog.jobbole.com/all-p... 八、scrapy-redis编写分布式爬虫代码原理 其余应用办法和单机版爬虫一样

November 16, 2020 · 1 min · jiezi

关于scrapy:34scrapy信号详解

【百度云搜寻,搜各种材料:http://www.lqkweb.com】【搜网盘,搜各种材料:http://www.swpan.cn】信号个别应用信号散发器dispatcher.connect(),来设置信号,和信号触发函数,当捕捉到信号时执行一个函数 dispatcher.connect()信号散发器,第一个参数信号触发函数,第二个参数是触发信号, 以下是各种信号 signals.engine_started当Scrapy引擎启动爬取时发送该信号。该信号反对返回deferreds。signals.engine_stopped当Scrapy引擎进行时发送该信号(例如,爬取完结)。该信号反对返回deferreds。 signals.item_scraped(item, response, spider)当item被爬取,并通过所有 Item Pipeline 后(没有被抛弃(dropped),发送该信号。该信号反对返回deferreds。 参数: item (Item 对象) – 爬取到的item spider (Spider 对象) – 爬取item的spider response (Response 对象) – 提取item的response signals.item_dropped(item, exception, spider)当item通过 Item Pipeline ,有些pipeline抛出 DropItem 异样,抛弃item时,该信号被发送。该信号反对返回deferreds。 参数: item (Item 对象) – Item Pipeline 抛弃的item spider (Spider 对象) – 爬取item的spider exception (DropItem 异样) – 导致item被抛弃的异样(必须是 DropItem 的子类) signals.spider_closed(spider, reason)当某个spider被敞开时,该信号被发送。该信号能够用来开释每个spider在 spider_opened 时占用的资源。该信号反对返回deferreds。 参数: spider (Spider 对象) – 敞开的spider reason (str) – 形容spider被敞开的起因的字符串。如果spider是因为实现爬取而被敞开,则其为 'finished' 。否则,如果spider是被引擎的 close_spider 办法所敞开,则其为调用该办法时传入的 reason 参数(默认为 'cancelled')。如果引擎被敞开(例如, 输出Ctrl-C),则其为 'shutdown' 。 ...

November 16, 2020 · 2 min · jiezi

关于scrapy:33Scrapy数据收集Stats-Collection

【百度云搜寻,搜各种材料:http://www.lqkweb.com】【搜网盘,搜各种材料:http://www.swpan.cn】Scrapy提供了不便的收集数据的机制。数据以key/value形式存储,值大多是计数值。 该机制叫做数据收集器(Stats Collector),能够通过 Crawler API 的属性 stats 来应用无论数据收集(stats collection)开启或者敞开,数据收集器永远都是可用的。 因而您能够import进本人的模块并应用其API(增加值或者设置新的状态键(stat keys))。 该做法是为了简化数据收集的办法: 您不应该应用超过一行代码来收集您的spider,Scrpay扩大或任何您应用数据收集器代码外头的状态。 数据收集器的另一个个性是(在启用状态下)很高效,(在敞开状况下)十分高效(简直觉察不到)。 数据收集器对每个spider放弃一个状态表。当spider启动时,该表主动关上,当spider敞开时,主动敞开。 数据收集各种函数 stats.set_value('数据名称', 数据值)设置数据stats.inc_value('数据名称')减少数据值,自增1stats.max_value('数据名称', value)当新的值比原来的值大时设置数据stats.min_value('数据名称', value)当新的值比原来的值小时设置数据stats.get_value('数据名称')获取数据值stats.get_stats()获取所有数据 举例: # -*- coding: utf-8 -*-import scrapyfrom scrapy.http import Request,FormRequestclass PachSpider(scrapy.Spider): #定义爬虫类,必须继承scrapy.Spider name = 'pach' #设置爬虫名称 allowed_domains = ['www.dict.cn'] #爬取域名 def start_requests(self): #起始url函数,会替换start_urls return [Request( url='http://www.dict.cn/9999998888', callback=self.parse )] # 利用数据收集器,收集所有404的url以及,404页面数量 handle_httpstatus_list = [404] # 设置不过滤404 def __init__(self): self.fail_urls = [] # 创立一个变量来贮存404URL def parse(self, response): # 回调函数 if response.status == 404: # 判断返回状态码如果是404 self.fail_urls.append(response.url) # 将URL追加到列表 self.crawler.stats.inc_value('failed_url') # 设置一个数据收集,值为自增,每执行一次自增1 print(self.fail_urls) # 打印404URL列表 print(self.crawler.stats.get_value('failed_url')) # 打印数据收集值 else: title = response.css('title::text').extract() print(title)更多:http://scrapy-chs.readthedocs... ...

November 13, 2020 · 1 min · jiezi

关于scrapy:32scrapy的暂停与重启

【百度云搜寻,搜各种材料:http://www.lqkweb.com】【搜网盘,搜各种材料:http://www.swpan.cn】scrapy的每一个爬虫,暂停时能够记录暂停状态以及爬取了哪些url,重启时能够从暂停状态开始爬取过的URL不在爬取 实现暂停与重启记录状态 1、首先cd进入到scrapy我的项目里 2、在scrapy我的项目里创立保留记录信息的文件夹 3、执行命令: scrapy crawl 爬虫名称 -s JOBDIR=保留记录信息的门路 如:scrapy crawl cnblogs -s JOBDIR=zant/001 执行命令会启动指定爬虫,并且记录状态到指定目录 爬虫曾经启动,咱们能够按键盘上的ctrl+c进行爬虫 进行后咱们看一下记录文件夹,会多出3个文件 其中的requests.queue文件夹里的p0文件就是URL记录文件,这个文件存在就阐明还有未实现的URL,当所有URL实现后会主动删除此文件 当咱们从新执行命令:scrapy crawl cnblogs -s JOBDIR=zant/001  时爬虫会依据p0文件从进行的中央开始持续爬取,

November 13, 2020 · 1 min · jiezi

关于scrapy:30将selenium操作谷歌浏览器集成到scrapy中

【百度云搜寻,搜各种材料:http://www.lqkweb.com】【搜网盘,搜各种材料:http://www.swpan.cn】1、爬虫文件 dispatcher.connect()信号散发器,第一个参数信号触发函数,第二个参数是触发信号,signals.spider_closed是爬虫完结信号 # -*- coding: utf-8 -*-import scrapyfrom scrapy.http import Request,FormRequestfrom selenium import webdriver # 导入selenium模块来操作浏览器软件from scrapy.xlib.pydispatch import dispatcher # 信号散发器from scrapy import signals # 信号class PachSpider(scrapy.Spider): #定义爬虫类,必须继承scrapy.Spider name = 'pach' #设置爬虫名称 allowed_domains = ['www.taobao.com'] #爬取域名 def __init__(self): #初始化 self.browser = webdriver.Chrome(executable_path='H:/py/16/adc/adc/Firefox/chromedriver.exe') #创立谷歌浏览器对象 super(PachSpider, self).__init__() #设置能够获取上一级父类基类的,__init__办法里的对象封装值 dispatcher.connect(self.spider_closed, signals.spider_closed) #dispatcher.connect()信号散发器,第一个参数信号触发函数,第二个参数是触发信号,signals.spider_closed是爬虫完结信号 #运行到此处时,就会去中间件执行,RequestsChrometmiddware中间件了 def spider_closed(self, spider): #信号触发函数 print('爬虫完结 进行爬虫') self.browser.quit() #敞开浏览器 def start_requests(self): #起始url函数,会替换start_urls return [Request( url='https://www.taobao.com/', callback=self.parse )] def parse(self, response): title = response.css('title::text').extract() print(title)2、middlewares.py中间件文件 ...

November 10, 2020 · 1 min · jiezi

关于scrapy:scrapy三-爬取ConceptNet

一、工作背景放弃之前的打算:通过开会讨论,仅爬取心理学畛域的常识来构建心理沙盘的常识图谱是不可取的(事实上,我的项目的指标是依据用户设计的沙盘场景推理出用户的心理状态,而不是做心理学百科知识的科普)。这一常识图谱构建方向上的扭转归功于咱们小组的探讨和 《常识图谱-概念与技术》 这本书对我的启发,一些常识要点如下(能够跳过间接查看我的项目细节): 1、常识图谱狭义概念为了讲明确我对我的项目的了解,还要从人工智能说起(想在这里一次性的的捋分明,兴许未来会退出一个链接):图:常识图谱的学科位置 人工智能有3个学派:符号主义、连贯主义和行为主义;常识工程源于符号主义,为了无效的利用常识,首先要在计算机系统中正当的示意常识;而常识示意的一个重要形式就是常识图谱;留神:常识图谱只是常识示意中的一种,除了语义网络以外,谓词逻辑、产生式规定、本体、框架、决策树、贝叶斯网络、马尔可夫逻辑网都是常识示意的模式; 2、KG钻研意义KG是认知智能的基石 机器了解数据的实质是从数据到常识图谱中的常识因素(实体概念、关系)的映射;了解过程能够视作建设从数据(文本、图片、语音、视频)到KG(脑海)中实体、概念、属性之间的映射过程;几点KG对于认知智能的重要性:①机器语言认知人类对语言的了解建设在认知能力根底之上,所以解释了咱们听不懂东方的笑话故事。语言了解须要背景常识,机器了解自然语言当然也须要背景常识了。②赋能可解释人工智能“解释”与符号化常识图谱密切相关,人只能了解符号而无奈了解数值,书中有三个很好的例子: 问鲨鱼为什么可怕?你可能解释因为鲨鱼是肉食动物——用概念在解释;问鸟为什么能翱翔?你可能会解释因为它有翅膀——用属性解释;问前段时间鹿晗和关晓彤为什么会刷屏?你可能会解释因为她是他女朋友——用关系在解释;③有助于加强机器学习的能力人类的学习高效、强壮,并不需要机器学习那样宏大的样本量,根本原因在于人类很少从零开始学习,人类善于联合丰盛的先验常识。 3、常识常识图谱常识图谱能够依据其所涵盖的常识分为四类:事实常识、概念常识、词汇常识和常识常识有了1和2的铺垫,咱们抉择为心理沙盘我的项目建设一个常识常识图谱的理由就明确了,每一个沙盘实体都来自事实世界,咱们要做的是高度还原人脑中实体与实体、实体与概念、概念与概念这些映射关系,从而可能让心理测试后果更健壮和有说服力。以沙盘形容中的虾为例: ①虾看似慢吞吞的游,遇到对手时它骁勇奔下来舒展双臂与它博斗,打断双臂在所不惜,象征充斥阳刚之气。②虾须晦涩,飘逸,虾尾随移其形而动,象征共性和指标。咱们能够构建这样一种分割: 二、工作思路沙盘心理分析师提供了一个entity文件,里边有大概600个实体,长这样:1、以这600个实体为根节点,从ConceptNet上爬取实体的所有关系,再递归关系所牵的另一边实体,提取的内容有:entity1、relation、entity2、att1、att2、weight、id此七项内容2、依据这些内容先构建一个常识图谱 三、scrapy实操1、在之前创立的爬虫工程中,新建一个spider文件,还是通过命令来实现(工程项目创立的具体操作步骤参考scrapy(一) 爬取心理学畛域词汇)scrapy genspider -t basic conceptSpider api.conceptnet.io 2、剖析页面,试探爬取——周而复始直到成型①方法论:当有一个新的爬虫工作时,我必然不能也绝不可能做到间接写成spider文件,解正文settings.py中的pipline,写items.py文件,写pipline.py文件。因为网页是否容许爬取、网页的格局、咱们想要的内容在哪、是否须要递归等,都须要去debug,缓缓的磨进去。也就是先别解正文settings.py中的pipline,只消应用命令$ scrapy crawl conceptSpider --nolog去一步步的迭代测验咱们的规定是否写对了。②页面剖析:查看ConceptNet官网文档,得悉这种api类型的网页中,每一个key代表什么。先给start_urls中只增加了一个‘http://api.conceptnet.io/c/en/apple’来专一于剖析这个页面,显然每一页都有共性,页面局部截图如下:其中’edges‘是一个list模式,每一项是一个关系,连贯着与apple相干的实体;在网页底部,有一个键值是‘view’,是管前后页的,也就是说里边有下一页的url;网页解析: # 将json格局的api页面解析为用字符串示意的字典js_str=response.xpath("//pre").xpath("string(.)").extract()[0].strip()# 将字符串转化为字典js=json.loads(js_str)规则化提取: for edge in js['edges']: str=edge['@id'].replace('[','').replace(']','').replace('/a/','').split(',') # 只取英文关系 if str[1][3:6]!='en/' or str[2][3:6]!='en/': continue # 取两个实体 e1=str[1].replace('/c/en/','').replace('/n','').replace('/wn','')[:-1].split('/',1) e2=str[2].replace('/c/en/','').replace('/n','').replace('/wn','')[:-1].split('/',1) # 取关系 r=str[0].replace('/r/','')[:-1] # 摘除后边的标识,放到属性里 e1_att='' e2_att='' if len(e1)==2: e1_att=e1[1] if len(e2)==2: e2_att=e2[1]注:测试规则化提取失常后,就能够在上边的for循环里边用item传给pipline去输入了。③页面跳转 if 'view' in js and 'nextPage' in js['view']: relPos = js['view']['nextPage'] print("进入衍生页面执行parse:") nexthref = self.url_std+relPos print(nexthref) yield scrapy.Request(nexthref, callback=self.parse)留神:这里有坑,如果只判断'nextPage' in js['view'],你就会发现有的实体页面中没有view这个键值,会产生谬误,但不影响pipline输入的后果。 ...

September 21, 2020 · 2 min · jiezi

关于scrapy:scrapy二-递归爬取心理学词汇

一、工作背景1、简略回顾上一期常识获取思路:从搜狗下载心理学词库,而后爬取这些词汇的百度百科页面。然而这些词汇只有3600个,当初咱们要丰盛实体,为下一阶段的命名实体辨认做筹备。 2、下一步工作打算step1:爬取百度百科心理学分类下的所有名词;step2:所有整合后的词汇,人为对其进行实体分类;step3:爬取《壹心理》中的文章,分词、标注、命名实体辨认(为关系抽取做筹备)ps:其实这个打算因为某些起因被放弃了(因为这篇文章是草稿,这段话是隔了两周后增加的) 3、这篇文章次要内容:递归爬取下图(百度百科凋谢分类页面)中所有的标签及子类别下的所有标签(相干分类栏目除外):指标: 上图中①②③中的条目是咱们须要增加到词汇汇合中的,②下的条目还须要进一步到上级链接去爬取。留神: ③下的条目不够齐备,须要去下一页爬取,上面会具体解说步骤。 二、工作记录1、此爬虫有一个根节点,所以start_urls内只有一个url:start_urls.append('http://baike.baidu.com/fenlei/心理学')2、想要迭代爬取一个标签下的所有标签:main_sub=response.xpath("./div[@class='category-title ']/*") # 应用了星号,再: for sub in main_sub: nexthref=sub.xpath("./@href") if(nexthref!=[]): nexthref=nexthref.extract()[0].strip() nexthref = response.urljoin(nexthref) yield response.follow(nexthref, callback=self.parse) print(nexthref) title=sub.xpath("string(.)").extract()[0].strip() if(title!="|" and title!="上级分类"): item['name']=title yield item即可;3、如上代码中,不管在程序任何地位,只有失去url,即可对其执行parse与yield: 细节1、对于下一节内容如何爬取,附上解决问题的链接《scrapy中如何获取下一页链接》留神:不能手动往start_urls中append()增加新的链接,因为在解析时候曾经把队列存入内存。2、两种在parse内持续爬取链接的形式 yield response.follow(nexthref, callback=self.parse)yield scrapy.Request(nexthref, callback=self.parse)3、解决一个bug递归爬取链接有效:解决:1、第一次不能是因为allowed_domains的限度2、第二次是因为在div标签下有两个链接:<上一页>和<下一页>,果然后果只爬取了3个,第2页,第1页和第1页(因为scrapy的机制,爬过第二页所以不会从新爬取了)4、对于yield item了解其实很简略,在哪用都成,就是一个生成器

September 18, 2020 · 1 min · jiezi

关于scrapy:抓取的模板适配工具-Portia-的使用

按官网下载启动 docker-compose up -d 拜访 localhost:9001, 后果404进到容器,发现 /app/portiaui/dist 文件夹下是空的。下载 nodejs,yarn 应用 yarn 编译: error ember-run-raf@1.1.2: The engine "node" is incompatible with this module. Expected version "~4.1.1". Got "10.22.0"error Found incompatible module.查一下官网把 package.json 里的 ember-run-raf 降级到 1.1.3, 编译通过 用 npm run build 编译胜利。 docker-compose up -d 启动:

August 3, 2020 · 1 min · jiezi

关于scrapy:scrapy爬虫框架和selenium的使用对优惠券推荐网站数据LDA文本挖掘

原文链接:http://tecdat.cn/?p=12203介绍每个人都喜爱省钱。咱们都试图充分利用咱们的资金,有时候这是最简略的事件,能够造成最大的不同。长期以来,优惠券始终被带到超市拿到折扣,但应用优惠券从未如此简略,这要归功于Groupon。 Groupon是一个优惠券举荐服务,能够在您左近的餐馆和商店播送电子优惠券。其中一些优惠券可能十分重要,特地是在打算小组活动时,因为折扣能够高达60%。 数据这些数据是从Groupon网站的纽约市区域取得的。网站的布局分为所有不同groupon的专辑搜寻,而后是每个特定groupon的深度页面。网站外观如下所示: 两个页面的布局都不是动静的,所以建设了一个自定义scrapy ,以便疾速浏览所有的页面并检索要剖析的信息。然而,评论,重要的信息,通过JavaScript出现和加载 。Selenium脚本应用从scrapy获取的groupons的URL,本质上模拟了人类点击用户正文局部中的“next”按钮。 for url in url_list.url[0:50]: try: driver.get(url) time.sleep(2) #Close Any Popup That Occurs# # if(driver.switch_to_alert()): try: close = driver.find_element_by_xpath('//a[@id="nothx"]') close.click() except: pass time.sleep(1) try: link = driver.find_element_by_xpath('//div[@id="all-tips-link"]') driver.execute_script("arguments[0].click();", link) time.sleep(2) except: next i = 1 print(url) while True: try: time.sleep(2) print("Scraping Page: " + str(i)) reviews = driver.find_elements_by_xpath('//div[@class="tip-item classic-tip"]') next_bt = driver.find_element_by_link_text('Next') for review in reviews[3:]: review_dict = {} content = review.find_element_by_xpath('.//div[@class="twelve columns tip-text ugc-ellipsisable-tip ellipsis"]').text author = review.find_element_by_xpath('.//div[@class="user-text"]/span[@class="tips-reviewer-name"]').text date = review.find_element_by_xpath('.//div[@class="user-text"]/span[@class="reviewer-reviewed-date"]').text review_dict['author'] = author review_dict['date'] = date review_dict['content'] = content review_dict['url'] = url writer.writerow(review_dict.values()) i += 1 next_bt.click() except: break except: nextcsv_file.close()driver.close()从每个组中检索的数据如下所示。 ...

July 18, 2020 · 2 min · jiezi

如何打造一个上千Star的Github项目

前言每一个程序员都或多或少接触过Github,至少是听说过吧。而Github最大的好处是在于程序员可以不用付出任何费用,可以在上面参考、借鉴甚至是照搬其他人贡献的项目,因为这一切都是开源的。另外,任何一个Github用户也可以在上面对自己感兴趣的项目做出贡献。所谓贡献,就是对已有的代码进行更正、优化、开发等操作,让项目发展得越来越棒。而且,Github的Star机制让项目的受欢迎程度得到很好的展示。如果您去Github上搜索一个Vue的后台管理模板,您很可能会选择几万Star的Vue-Element-Admin(就像您去挑选晚餐地点,一般会去大众点评上选评价足够高的餐厅)。千万别小看Star这样类似点赞的机制,这些Star的背后是大多数程序员的认可,Github Star数量可比朋友圈的点赞数量要有技术含量得多。我不是在吹捧那些点赞数多的项目,我只是在强调一种增加技术影响力的方式:打造一个上千Star的Github项目。Github作为世界上最大的开源项目管理中心,可以让任何人有机会实现这个目标。 另外,作者只是一个普通人,是一点一滴尝试了很多办法、做出了很多努力才收获了上千Star,并没有很多大佬那样更出色的项目。作者将从自己的角度给大家介绍自己积累的经验教训,从项目定位、产品开发、推广渠道等方面来讲。如果大佬们有更多更优秀的作品和经验,欢迎随时交流。 关于作者的项目Crawlab是作者近期在开发的Github项目,是一个专注于爬虫的管理平台。这个项目从今年3月份上线以来,到现在总共收到了大约1.1k个Github Stars(如下图)。 最初Crawlab是基于Celery的分布式爬虫管理平台,后来由于稳定性、性能等考虑,在v0.3.0版本中将Python Celery改为了Golang,稳定性和性能都得到了极大的提升。Crawlab不仅支持主流的爬虫框架,例如Scrapy,还支持Python、NodeJS、Go、Java、PHP等多种编程语言以及多种爬虫框架。Crawlab的目的是让爬虫工程师以最轻松的方式来管理和运行他们开发的爬虫。Crawlab自上线以来,一直受到爬虫爱好者们和开发者们的好评,不少使用者还表示会用 Crawlab 搭建公司的爬虫平台。在文末有关于Crawlab的往期文章,想要了解更多Crawlab的读者可以去看一下。 Github: https://github.com/tikazyq/crawlab 寻找痛点任何一个产品,都是为需要的人服务的。这个受众可以是您自己,也可以是您的朋友,也可以是完全不认识的陌生人。此外,一个优秀的产品必须解决用户的问题,或者说是痛点。就像雪中送炭那样,恰当的时间出现了恰当的解决办法,别人才会毫不犹豫的使用这个东西。分布式爬虫工具PySpider(13.5k stars)为什么那么受欢迎,就是因为它解决了那些需要抓取大量网站的爬虫开发工程师的管理困难的痛点。Web框架Flask(46k stars)因为其解决了Web开发上手困难的问题(相比于Django、Tornado这样的传统框架),受到了Web开发者的喜爱,在Github上占据一席之地。基于Vue Element的管理后台框架 Vue-Element-Admin(39k stars)让前端开发不用从零开始搭建管理后台,开箱即用,成为Vue开发者的香饽饽。如何寻找到用户的痛点是我们能打造一个优秀产品或项目的首要问题。 从自身周围寻找用户痛点您可能会纳闷,我周围没有感觉到有痛点的用户。如果您这么觉得,您一定是没有注意观察。在工作中我们会处理成千上万的问题,包括一些技术问题或非技术问题。而这些问题的产生,一定是有没有满足到的需求导致的,而这正是可能的出发点。 例如,作者的开源爬虫管理平台Crawlab就是在思考一个工作问题时诞生的。作者所在的部门有上百个爬虫,其中包括了Selenium爬虫和其他类型的爬虫。我们当时的爬虫管理方式和实现方式都有非常多的局限性,导致了扩展性不高、排查异常困难等问题。我们有一个Web UI界面,但是仅仅局限于业务,没有专注于爬虫本身。作者当时思考,是不是只有我们公司才遇到这个问题,还是这个问题是一个普遍问题,几乎每个需要爬虫的公司都会遇到。为了验证这个假设,作者花了半个月的时间做了一个最小可行性产品(MVP),Crawlab v0.1版本,只有最基本的执行爬虫脚本的功能。结果,第一版发布后陆陆续续收到正面反馈,也有不少改进建议。第一天的Star数就达到了30,后面两天涨到了100。这验证了我的假设,爬虫管理困难这个问题是普遍存在的,大家都觉得Crawlab是个不错的idea,愿意来尝试。这才开始让作者更有动力不断完善这个产品。所以,从身边的问题出发是个很好的开始。 扩大自己的知识圈知识就是力量,这句话很正确。在开发产品的过程中我们不仅需要了解自身产品,还需要了解自己的客户,更需要了解自己产品的市场及竞争对手。我们需要不断完善更新自己的知识库,以在后续的开发、推广产品过程中作出最优的选择。扩大知识圈的渠道有很多,掘金就是一个很不错的渠道,上面不仅有各种优质的技术文章,更有掘金小册,可以帮助读者快速了解一项技术。除了掘金以外,还有其他很多优秀的技术网站,包括SegmentFault、GitChat、V2ex等等。相信各位读者及大佬也有自己获取知识的渠道,可以加作者微信tikazyq1分享交流下。 以自己举例,在开发Crawlab之前,我已经是掘金的重度阅读者,而且还购买了韦世东写的掘金小册《Python 实战:用 Scrapyd 打造个人化的爬虫部署管理控制台》,在小册中不仅了解了爬虫部署管理平台的原理和基础知识,还了解到了市场上已存在的爬虫管理平台Gerapy。这为后来我开发Crawlab积累了大量的宝贵经验。我又了解了市面上所有的爬虫平台,无一例外是基于Scrapyd的,因此我在想万一有想要管理非scrapy爬虫的呢,他们会使用什么工具来管理。后面我又做了些研究,发现Crawlab才是他们解决该问题的方法。因此,花一些钱购买知识是非常值得的,我在获取知识的同时帮助了我寻找痛点。 完善产品您可能会认为本小节是在讲如何开发产品,但不是。本小节将讲如何在开发产品中花最少的时间干最正确的事情。用户满意了,增加Star数是自然而然的事情。 我们不可能在第一时间做到一步到位。因此,不断完善产品来满足用户需求变得尤为重要。《精益创业》中的作者定义了最小可行性产品(Minimal Viable Product,MVP),也就是以最低成本尽可能展现核心概念的产品策略。因为我们的时间很宝贵(对于经常需要加班的朋友来说,更是如此),花费大量时间在完善各种不必要的功能上会是极为浪费的行为。我们没有必要花时间开发那些用户认为不重要的功能。如何做到不浪费时间,只开发用户喜爱的功能呢? 询问用户直接询问用户是最为直接也是最有效的方式。我在发布完Crawlab第一版的时候成立了一个微信群,并在推广的时候邀请用户加入,因此积累了一部分实际用户与潜在用户。我在开发一个新功能前我会询问群里的朋友,他们是否喜爱这样一个功能,如果开发这样的功能他们是否会使用。我询问群友是否都在用Crawlab,很多人都回答感兴趣但是没有。这显然是个令人失望的答案,但我并没有丧失信心。我接着问了为什么,结果他们都认为Crawlab虽然不错,但部署太麻烦了。然后我在群里问了他们关于Docker的意见,群友一致认为如果有Docker会非常棒。而现在,Docker变成了部署Crawlab的首选项,几乎每一个用户都是用的Docker来部署Crawlab。 另外一个有效的询问用户的方式是问卷调查。当Crawlab的Golang版本v0.3.0发布后,我在群里发放了问卷调查,邀请用户回答他们认为最重要的功能,答案如下图。统计后发现,任务监控和可配置爬虫是最为重要的两个功能。因此,我会在接下来的开发过程中优先考虑开发这两个功能。 统计用户行为现在的大公司都会在网站或App中做埋点上报统计用户行为数据。这是也是非常有效的了解用户偏好的工具,而且这种方法还排除了用户偏见(问卷中被调查者可能心口不一)。在Crawlab中,嵌入了一小段JS代码,让用户行为数据得到统计,上传到第三方统计工具百度统计上面。下图是用户用得最多的行为。 从该报表可以看到,用户主要在爬虫页面和任务页面来回切换标签,我可能还不知道它是哪些标签,但我肯定会在这两个页面上下更多功夫,来优化Crawlab。当然,这一切的用户数据收集都是经过用户同意的,用户如果在首次加载选择不同意的话,数据将不会上传(有些框架都不会询问用户的意愿,它们会直接上传统计数据)。 其他完善产品的工具例如A/B测试作者不会讲了,因为这要求更多的资源和流量,Crawlab还没有这样雄厚的资源。感兴趣的可以自己去百度。 产品推广如果没有人了解您的产品,您的产品再优秀也只能被凉在一边,无人问津,沾染灰尘。因此,推广您的产品也是增加Github Star数的非常重要的途径。下面我将介绍一些常用的产品推广的方式,包括一些常用的有效渠道,以及如何查看后台数据来监控渠道有效性。 写技术文章这是我认为最有效的渠道了。在推广Crawlab的实践中,我发现在掘金上写文章是一个非常重要的推广产品的方式。下图是用户通过各种渠道(微信群、朋友圈、掘金自然流量)接触到技术文章方式。 将您的文章展示给更多用户有助于提高您产品的曝光度,而且如果用户对您产品感到满意的话,会点击您嵌入到文章中的导航到Github项目地址的链接,然后给您项目Star。我每次在掘金上写完文章之后,我都会将文章的链接发到各个相关的微信群里,感兴趣的群友会点击链接到文章里,从而更有可能到Github上给项目点Star。同理,我也会发布到朋友圈或其他渠道。如果文章读者不会第一时间Star,没关系,他在了解到您项目之后很可能会在后面的曝光过程给您Star。在市场营销中,这就叫再营销(Remarketing)。千万不要觉得写文章是一件没有用的事情,相反,它将帮助您更早地收获上千Star项目。 当然,我们不仅仅有掘金这一个渠道,我们还有很多其他选择。下面列出了我能够知道的推广渠道。 渠道简介掘金偏前端的技术社区V2ex技术论坛GitChat技术知识分享平台微信公众号不用过多介绍了SegmentFault技术问答、技术博客网站知乎知识问答网站CSDNIT技术社区开源中国开源技术交流社区简书博客网站其他读者可以微信我tikazyq1添加您应该定期去Github上查看您的流量来源,看看哪些渠道是有用的。具体地址是: 主页 -> Insights -> Traffic。Crawlab最近30天的Traffic如下图。 可以看到,Github内部、掘金以及V2ex是Crawlab的三大流量来源。上图中8月14号的流量高峰是因为我在当天发了一篇文章《如何快速搭建实用的爬虫管理平台》。 当然,要发布这么多文章这么多平台不是一件容易的事情。作者和另外一些朋友打算基于爬虫的方式,写一个自动发布文章的工具,名字叫ArtiPub(意思为Article Publisher),Github为 https://github.com/crawlab-te... 。现在框架搭建好了,准备不断开发。欢迎大家随时关注。 改造Github首页光是有流量还不行,您还需要对让自己的README显得更加具有吸引力。下列是几个增加吸引力的内容,建议您都该考虑加入到您的项目主页中。 徽章中英文目录产品截图使用安装社区以上几种方式都可以让您的Github首页显得更加专业。您需要清晰地阐述您的项目的安装方式,以及中文介绍,这将有利于让您的读者更加容易上手您的产品。产品截图是非常有效的展示您产品的方式,人都是视觉动物,他们会更倾向于有截图的产品(Airbnb就做的很不错,他们在房屋截图中用了大光圈照片)。如果您能够加上Logo之类的就更棒了。 下图是Crawlab的首页,虽然不完美,但对于增加吸引力来说很有效。 项目管理项目管理是一个可选项,但对于推进和监控项目进度来说是非常有效的。可以用酷炫的项目管理工具,例如Teambition、禅道或Trello,也可以用简单的Excel。我在Crawlab中就是用的Excel。下图是早期Crawlab项目管理的电子表格。 如何进行项目管理,这里我就不详细讲了,因为我也不是专业项目管理经理,也没有PMP证书。后期如果有需求的话我可以在另一篇文章中专门介绍项目管理。 总结本篇文章主要从自己项目Crawlab的角度出发,介绍了如何打造一个上千Star的Github项目的方法。其中包括寻找痛点、完善产品、产品推广和项目管理。相信每一个获得了上千Star的项目的作者都有自己的方法论。我看了老乡大佬CrossoverJie的相关文章《1K star+ 的项目是如何炼成的?》,获得了很多灵感,其中很多理念与本篇文章是相似的。不管如何,都祝愿读者能从本篇文章中收获知识,祝您能早日收获自己的上千Star项目。已经收获的,也可以分享下您的经验。 ...

August 17, 2019 · 1 min · jiezi

Scrapy-16-中文文档校对活动-ApacheCN

整体进度:https://github.com/apachecn/s... 贡献指南:https://github.com/apachecn/s... 项目仓库:https://github.com/apachecn/s... 贡献指南请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并不要求您做到十全十美,因此请不要担心因为翻译上犯错——在大部分情况下,我们的服务器已经记录所有的翻译,因此您不必担心会因为您的失误遭到无法挽回的破坏。(改编自维基百科)负责人: 简杨君:823139365章节列表简介第一步 Scrapy at a glance安装指南Scrapy 教程实例基本概念 命令行工具Spider选择器项目项目加载器Scrapy shell项目管道Feed 导出请求和响应链接提取器设置例外情况内置服务 Logging统计数据集合发送电子邮件远程登录控制台Web服务解决具体问题 常见问题调试spidersSpider 合约常用做法通用爬虫使用浏览器的开发人员工具进行抓取调试内存泄漏下载和处理文件和图像部署 SpiderAutoThrottle 扩展Benchmarking作业:暂停和恢复爬行延伸 Scrapy 体系结构概述下载器中间件Spider 中间件扩展核心API信号条目导出器其余所有 发行说明为 Scrapy 贡献版本控制和API稳定性流程一、认领首先查看整体进度,确认没有人认领了你想认领的章节。 然后回复 ISSUE,注明“章节 + QQ 号”(一定要留 QQ)。 二、校对需要校对: 语法术语使用文档格式如果觉得现有翻译不好,重新翻译也是可以的。 三、提交fork Github 项目将译文放在docs文件夹下pushpull request请见 Github 入门指南。

July 6, 2019 · 1 min · jiezi

python使用Scrapy框架抓取起点中文网免费小说案例

使用工具,ubuntu,python,pycharm一、使用pycharm创建项目:过程略二、安装scrapy框架 pip install Scrapy三、创建scrapy项目: 1.创建爬虫项目 scrapy startproject qidian2.创建爬虫,先进入爬虫项目目录cd qidian/scrapy genspider book book.qidian.com创建完成后项目目录如下 目录下的的book.py就是我们的爬虫文件 四、打开book.py编写爬虫的代码 1.进入需要爬去的书的目录,找到开始url设置start_url:#鬼吹灯图书目录start_urls = ['https://book.qidian.com/info/53269#Catalog']2、在创建项目的时候,筛选的url地址为:allowed_domains = ['book.qidian.com'] 打开图书章节后发现章节的url如下: # https://read.qidian.com/chapter/PNjTiyCikMo1/FzxWdm35gIE1 所以需要将read.qidian.com 加入allowed_domains 中,allowed_domains = ['book.qidian.com', 'read.qidian.com']剩下的就是通过xpath 获取抓取到的内容,提取我们需要的内容完整代码如下# -*- coding: utf-8 -*-import scrapyimport logginglogger = logging.getLogger(__name__)class BookSpider(scrapy.Spider): name = 'book' allowed_domains = ['book.qidian.com', 'read.qidian.com'] start_urls = ['https://book.qidian.com/info/53269#Catalog'] def parse(self, response): # 获取章节列表 li_list = response.xpath('//div[@class="volume"][2]/ul/li') # 列表循环取出章节名称和章节对应的url for li in li_list: item = {} # 章节名称 item['chapter_name'] = li.xpath('./a/text()').extract_first() # 章节url item['chapter_url'] = li.xpath('./a/@href').extract_first() # 获取到的url //read.qidian.com/chapter/PNjTiyCikMo1/TpiSLsyH5Hc1 # 需要重新构造 item['chapter_url'] = 'https:' + item['chapter_url'] # 循环抓取每个章节的内容 if item['chapter_url'] is not None: # meta:传递item数据 yield scrapy.Request(item['chapter_url'], callback=self.parse_chapter, meta={'item': item}) def parse_chapter(self, response): item = response.meta['item'] # 获取文章内容 item['chapter_content'] = response.xpath('//div[@class="read-content j_readContent"]/p/text()').extract() yield item五、将爬去数据保存到mongodb中 ...

June 28, 2019 · 1 min · jiezi

爬虫爬-JSON-HTML-数据

最近这两周在忙着给公司爬一点数据,更文的速度有一点下降,预计今天就爬完了,总结总结经验。 其实之前我司是有专门做爬虫的,不用前端这边出人干活。后来那人离职了,有可能就没有爬虫这方面的需求了。突然又有了一些,前端这边出人做一下。老大说用 py 做,前期先调研一下。 原理爬虫其实原理上很简单,我们==客户端,他们==服务端。客户端发送请求 req,服务端返回响应 rsp。拿到响应之后解析数据,入库,就完事了。 请求数据 req一般来说请求分为两种,拉数据 get 比较多。偶尔部分接口需要登录,那就是多带 cookie 或者 headers。其实还有一部分工作就是分析入参。 get参数拼接在 url 上post参数放在 body 里响应数据 rsp返回数据大体上是两种 JSON一般来说,通过 抓包 或者说 network 工具。我们找到了服务端的接口,那么我直接访问这个接口即可。本文第一个重点来了:切换到移动端再查一遍,往往有不一样的收获,一般来说 PC 和 M 端的进度不了,有可能都不是一个项目组,所以实现方式就会有差别。html比较坑的一种方式,因为没有找到 JSON 接口。无奈只能走解析 HTML 的路子。调研Node 之前给后台搭架子的时候使用过,主要功能点如下: 自动登录,(拿headers、cookie)存储本地,每次请求带上 token启动代理服务py 老大说要用这个东西。咨询了一下其他朋友,说可以使用下面的工具。 requests + beautifulSoup使用起来其实就是 requests 发请求, beautifulSoup 解析 HTML。比较原始。scrapy一个爬虫的框架。我在这里学的 www.scrapyd.cn。实现上比较完整,可以设置请求间隔,随机 ua 等功能。前端实现 我一个铁头娃,怎么能轻言放弃?身为一个前端er,还是这些 api 让我更加亲切 XHR发请求利器,打开对方页面,cookie 啥的都自带。无敌就是这么寂寞。其实还可以找到对方请求发起的位置,打个断点,把对方内部的代码绑定到全局,这样一些内部逻辑什么的也都没问题。而且还 JSON HTML 通吃。iframe针对 HTML 类型的处理。同域的情况下,也无敌好吗? HTML 获取 DOM 节点?甚至可以取 window 上的对象。vue SSR 你感觉到了威胁吗?网上其他服务商提供的接口(真香啊)。有免费的有收费的,一般免费的限量。 ...

June 19, 2019 · 2 min · jiezi

爬虫平台Crawlab-v02发布

Crawlab是一个专注于爬虫的集成了爬虫管理、任务调度、任务监控、数据分析等模块的分布式爬虫管理平台,非常适合对爬虫管理、爬虫工程化有要求的开发者及企业。对Crawlab还不了解的童鞋,请移步之前的文章: 分布式通用爬虫管理平台Crawlab手把手教你如何用Crawlab构建技术文章聚合平台(一)手把手教你如何用Crawlab构建技术文章聚合平台(二)Crawlab的任务调度核心模块是基于Celery的,因此天然支持分布式爬虫、多节点抓取。Crawlab虽然是用python写的,但爬虫不局限于python爬虫,理论上可兼容任何语言以及任何框架。从目前开源的框架来看,大部分爬虫平台是以scrapyd为核心,因此只能支持scrapy框架的爬虫,而Crawlab不仅支持scrapy,还支持其他框架的爬虫。 更新一览v0.2 已完成[x] 基础统计[x] 数据分析(爬虫)[x] 网站信息[x] 定时任务[x] 修复bug待开发[ ] 用户管理[ ] 上传爬虫[ ] 导出数据[ ] 高级数据分析(网站、任务)[ ] 更多爬虫例子[ ] 文件管理截屏基础统计(爬虫) 基础统计(任务) 定时任务 网站信息 __Github__: tikazyq/crawlab 如果感觉Crawlab还不错的话,请加作者微信拉入开发交流群,大家一起交流关于Crawlab的使用和开发。

May 10, 2019 · 1 min · jiezi

时隔五年Scrapyd-终于原生支持-basic-auth

Issue in 2014scrapy/scrapyd/issues/43 Pull request in 2019scrapy/scrapyd/pull/326 试用安装:pip install -U git+https://github.com/my8100/scrapyd.git@add_basic_auth更新配置文件 scrapyd.conf,其余配置项详见官方文档[scrapyd]username = yourusernamepassword = yourpassword启动:scrapydIn [1]: import requestsIn [2]: requests.get('http://127.0.0.1:6800/').status_codeOut[2]: 401In [3]: requests.get('http://127.0.0.1:6800/', auth=('admin', 'admin')).status_codeOut[3]: 401In [4]: requests.get('http://127.0.0.1:6800/', auth=('yourusername', 'yourpassword')).status_codeOut[4]: 200由于 Scrapyd 的 GitHub 最新提交已经重构了 Jobs 页面,如果正在使用 ScrapydWeb 管理 Scrapyd,则需同步更新 ScrapydWeb:pip install -U git+https://github.com/my8100/scrapydweb.gitGitHubmy8100/scrapyd

May 9, 2019 · 1 min · jiezi

使用python-scrapy爬取网页中带有地图展示的数据

最近有个需求,是要爬取某个物流公司的官网信息,我看了下官网,基本上都是静态页面比较好抓取,不像那种资讯类,电子商务类型的网站结果复杂,反爬严格,AJAX众多,还内心暗自庆幸,当我进一步分析时候发现并非普通的静态页面。例如这个URL界面,我要获取全中国各大城市的物流园区分布信息,并且要获取详情信息,这个页面里面是有个地图镶嵌,每个城市物流信息你要单独点击地图上的信息才能显示。https://www.glprop.com.cn/our... 我刚开始想,这种会不会是ajax请求呢,通过chrmoe抓包并没有发现,然后我查看网页源代码发现所有城市信息在一个scripts里面如图:然后各个园区的信息在一个叫park={xx}里面存着 原来都在这里面,直接获取源代码,正则匹配,开干。item: #普洛斯class PuluosiNewsItem(scrapy.Item): newstitle=scrapy.Field() newtiems=scrapy.Field() newslink=scrapy.Field()class PuluosiItem(scrapy.Item): assetstitle = scrapy.Field() assetaddress=scrapy.Field() assetgaikuang=scrapy.Field() assetpeople=scrapy.Field() asseturl = scrapy.Field()pipelines: class PuluosiNewsPipeline(object): def __init__(self): self.wb=Workbook() self.ws=self.wb.active #设置表头 self.ws.append(['普洛斯新闻标题','新闻发布时间','新闻URL']) self.wb2 = Workbook() self.ws2 = self.wb2.active self.ws2.append(['资产标题', '资产地址', '资产概况','其他信息','URL']) def process_item(self,item,spider): if isinstance(item, PuluosiNewsItem): line = [item['newstitle'], item['newtiems'], item['newslink']] # 把数据中每一项整理出来 self.ws.append(line) self.wb.save('PuluosiNews.xlsx') # 保存xlsx文件 elif isinstance(item,PuluosiItem): line = [item['assetstitle'], item['assetaddress'], item['assetgaikuang'],item['assetpeople'],item['asseturl']] self.ws2.append(line) self.wb2.save('PuluosiAsset.xlsx') # 保存xlsx文件 return itemspider: ...

April 26, 2019 · 2 min · jiezi

python的scrapy框架爬取懒人听书网站

项目地址:https://github.com/gejinnvshe...微信公众号:天字一等 爬取懒人听书平台书籍的书名、作者名、分类,后续还会增加爬取音频 爬虫用到的框架:scrapy Anaconda是专注于数据分析的Python发行版本 scrapy简单入门及实例讲解:https://www.cnblogs.com/kongz... scrapy进阶实例:https://blog.csdn.net/z564359... scrapy框架知识点 1、ROBOTSTXT_OBEY = False 粗解https://www.jianshu.com/p/19c1ea0d59c22、爬虫-User-Agent和代理池https://www.cnblogs.com/sunxiuwen/p/10112057.html3、scrapy项目配置文件:scrapy.cfg:爬虫项目的配置文件。__init__.py:爬虫项目的初始化文件,用来对项目做初始化工作。 items.py:爬虫项目的数据容器文件,用来定义要获取的数据。1、pipelines.py:爬虫项目的管道文件,用来对items中的数据进行进一步的加工处理。 2、scrapy的pipeline是一个非常重要的模块,主要作用是将return的items写入到数据库、文件等持久化模块settings.py:爬虫项目的设置文件,包含了爬虫项目的设置信息。 middlewares.py:爬虫项目的中间件文件,4使用anaconda prompt运行.py文件,执行scrapy crwal xx指令时,xx是.py文件中给name赋的值使用anaconda prompt运行.py文件,执行scrapy crwal xx指令时,如果报错说少了yy modules,直接输入pip install yy执行安装包,不用在进入对应的项目目录下5、 https://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/tutorial.html?highlight=extract xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.extract(): 序列化该节点为unicode字符串并返回list。re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。6、elastisearch查询语句https://segmentfault.com/q/1010000017553309/7、传入xpath表达式,返回该表达式所对应的所有节点的selector list列表extract(): 返回被选择元素的unicode字符串8、yieldyield的作用 这里是在爬取完一页的信息后,我们在当前页面获取到了下一页的链接,然后通过 yield 发起请求, # 并且将 parse 自己作为回调函数来处理下一页的响应 # https://www.jianshu.com/p/7c1a084853d8 yield Request(self.lrtsUrl + next_link, callback=self.parse, headers=headers) #获取下一页,parse是回调函数来处理下一页的响应9、meta scrapy的request的meta参数是什么意思?https://blog.csdn.net/master_ning/article/details/80558985 python基础知识点: class:#创建类 类就是一个模板,模板里可以包含多个函数,函数里实现一些功能def:#创建类中函数pass:pass 不做任何事情,一般用做占位语句。if name == '__main__':的作用https://www.cnblogs.com/kex1n/p/5975575.html5、python range() 函数可创建一个整数列表,一般用在 for 循环中。函数语法range(start, stop[, step])6、Python len() 方法返回对象(字符、列表、元组等)长度或项目个数。语法len()方法语法:len( s ) ...

April 25, 2019 · 1 min · jiezi

小程序开发一使用scrapy爬虫采集数据

过完年回来,业余时间一直在独立开发一个小程序。主要数据是8000+个视频和10000+篇文章,并且数据会每天自动更新。 我会整理下整个开发过程中遇到的问题和一些细节问题,因为内容会比较多,我会分成三到四篇文章来进行,本文是该系列的第一篇文章,内容偏python爬虫。 本系列文章大致会介绍一下内容: 数据准备(python的scrapy框架)接口准备(nodejs的hapijs框架)小程序开发(mpvue以及小程序自带的组件等)部署上线(小程序安全域名等配置以及爬虫/接口等线上部署维护) 数据获取 数据获取的方法有很多种,这次我们选择了爬虫的方式,当然写一个爬虫也可以用不同的语言,不同的方式。之前写过很多爬虫,这次我们选择了python的scrapy库。关于scrapy,百度百科解释如下: Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。 学习scrapy,最好的方式就是先阅读一遍文档(Scrapy 1.6 documentation),然后照着文档里的例子写一写,慢慢就熟悉了。里面有几个很重要的概念是必须要理解的: Items 官方对items的定义是“The main goal in scraping is to extract structured data from unstructured sources, typically, web pages.”,个人理解为数据结构,也就是要爬取数据的字段,最好能和数据库字段对应,便于入库。Spiders “Spiders are classes which define how a certain site (or a group of sites) will be scraped, including how to perform the crawl (i.e. follow links) and how to extract structured data from their pages (i.e. scraping items). ”,也就是爬虫比较核心的内容,定义爬虫的方式,一些策略,以及获取那些字段等等。pipelines ...

April 23, 2019 · 1 min · jiezi

如何免费创建云端爬虫集群

移步 GitHub

April 4, 2019 · 1 min · jiezi

Python爬虫框架scrapy入门指引

想爬点数据来玩玩, 我想最方便的工具就是Python scrapy了。 这框架把采集需要用到的功能全部封装好了,只要写写采集规则,其他的就交给框架去处理,非常方便,没有之一,不接受反驳。:)网上学习资源非常丰富,我这里介绍下我的学习方法,供大家参考。首先,大概看下python这门语言。 推荐阅读 廖雪峰的python3教程 看这个期间,你应该已经把python3跟IDE编辑器安装好了, IDE编辑器的话我推荐你使用 paycharm下载接着,就看看scrapy文档,英文好的看scrapy最新文档,不然就看scrapy中文文档。 跟着文档敲一敲基本上也就会玩了。如果文档看不懂的话,推荐看看这个教程 Python爬虫教程

March 20, 2019 · 1 min · jiezi

Scrapy框架get() 、getall() 、extract() 、extract_first()的区别

看官方文档(链接附在文末),看到了关于get()、get()方法的使用,查阅网络没有资料,那就自己记录一下。y( . )耶y( . )耶y( . )耶y( . )耶y( . )耶y( . )耶y( . )耶y( . )耶y( . )耶~先说结论:对于scrapy.selector.unified.SelectorList对象,getall()==extract(),get()==extract_first()对于scrapy.selector.unified.Selector对象,getall()==extract(),get()!=extract_first()使用scrapy shell 进行测试scrapy shell https://gavbus668.com/得到如下结果:皆是常规操作返回html的前200个字符,看看没有发生错误response.text[:200]得到:Out[3]: ‘<html>rn<head>rn <meta charset=“utf-8”>rn <meta http-equiv=“X-UA-Compatible” content=“IE=edge”>rn <meta name=“renderer” content=“webkit”>rn <meta name=“viewport” content=“width=device-widt’bingo继续,使用Scrapy Selector下一步操作In [5]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)Out[5]:[<Selector xpath=’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’ data=‘DNW-025 彼女が 制服に着替えたら。5’>, <Selector xpath=’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’ data=‘rntttttt’>, <Selector xpath=’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’ data=‘rntttttt’>, <Selector xpath=’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’ data=’ / ‘>]In [10]: type(response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’))Out[10]: scrapy.selector.unified.SelectorList发现使用Selector得到的是一个SelectorList对象实例所以get() 、getall() 、extract() 、extract_first()是SelectorList对象实例的方法继续使用get() 、getall() 、extract() 、extract_first(),观察区别:In [6]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’).get()Out[6]: ‘DNW-025 彼女が制服に着替えたら。5’In [7]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’).getall()Out[7]: [‘DNW-025 彼女が制服に着替えたら。5’, ‘rntttttt’, ‘rntttttt’, ’ / ‘]In [8]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’).extract()Out[8]: [‘DNW-025 彼女が制服に着替えたら。5’, ‘rntttttt’, ‘rntttttt’, ’ / ‘]In [9]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’).extract_first()Out[9]: ‘DNW-025 彼女が制服に着替えたら。5’over,总结一下:对于scrapy.selector.unified.SelectorList对象get() == extract_first()返回的是一个list,里面包含了多个string,如果只有一个string,则返回[‘我很孤独’]这样的形式getall() == extract()返回的是string,list里面第一个stringextract_first()与get()有区别与Selector对象有关In [17]: type(response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’))Out[17]: scrapy.selector.unified.SelectorListIn [18]: type(response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0])Out[18]: scrapy.selector.unified.SelectorIn [19]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0].get()Out[19]: ‘DNW-025 彼女が制服に着替えたら。5’In [20]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0].getall()Out[20]: [‘DNW-025 彼女が制服に着替えたら。5’]In [21]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0].extract()Out[21]: ‘DNW-025 彼女が制服に着替えたら。5’In [22]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0].extract_first()—————————————————————————AttributeError Traceback (most recent call last)<ipython-input-22-9eada5e1e561> in <module>—-> 1 response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0].extract_first()AttributeError: ‘Selector’ object has no attribute ’extract_first’In [23]: response.xpath(’//[@id=“waterfall”]/div[1]/a/div[2]/span/text()’)[0]Out[23]: <Selector xpath=’//*[@id=“waterfall”]/div[1]/a/div[2]/span/text()’ data=‘DNW-025 彼女が制服に着替えたら。5’>发现:对于Selector类型的对象,并不能使用extract_first()方法,而使用get()可以文末附官方文档链接链接Scrapy官方教程——关于get()、getall()方法 ...

March 18, 2019 · 1 min · jiezi

scrapy爬取Drupal网站,提示404错误

最近在学习Python的爬虫。以前坚持用nodejs做爬虫。前两天闲得无聊,在慕课上看了下scrapy的课程。然后发现这个框架的设计真模块化。所以就开始动手用scrapy爬取一些东西。然后我的目标网站是个drupal做的。分页抓取的时候,首页是正常的,爬取第二页的时候,大概率是抛错提示:404,要么就是给我返回了一些脏数据。这个网站还真是老谋深算啊。然后我仔细分析了下网站的请求头。然后加上了如下两条,请求就正常了:request.headers[‘accept’] = ’text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8’request.headers[‘cache-control’] = ’no-cache’看来还是得注意请求头的细节。

March 12, 2019 · 1 min · jiezi

Python爬虫框架Scrapy入门与实践之爬取豆瓣电影Top250榜单

前言爬虫就是请求网站并提取数据的自动化程序,其中请求,提取,自动化是爬虫的关键。Python作为一款出色的胶水语言自然成为了很多爬虫爱好者的首选,而使用Python开发的爬虫框架Scrapy当属目前最热门的解决方案之一。本文记录了目前网络上比较经典的Scrapy爬取豆瓣电影Top250榜单实践过程,作为Python爬虫框架Scrapy的入门案例。Python爬虫框架Scrapy入门与实践之爬取豆瓣电影Top250榜单更新历史2019年03月02日 - 初稿阅读原文 - https://wsgzao.github.io/post…扩展阅读Scrapy - https://scrapy.org/什么是爬虫?网络爬虫(又被称为网页蜘蛛,网络机器人,在 FOAF 社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。其实通俗的讲就是通过程序去获取 web 页面上自己想要的数据,也就是自动抓取数据爬虫可以做什么?你可以爬去妹子的图片,爬取自己想看看的视频。。等等你想要爬取的数据,只要你能通过浏览器访问的数据都可以通过爬虫获取爬虫的本质是什么?模拟浏览器打开网页,获取网页中我们想要的那部分数据浏览器打开网页的过程:当你在浏览器中输入地址后,经过 DNS 服务器找到服务器主机,向服务器发送一个请求,服务器经过解析后发送给用户浏览器结果,包括 html,js,css 等文件内容,浏览器解析出来最后呈现给用户在浏览器上看到的结果所以用户看到的浏览器的结果就是由 HTML 代码构成的,我们爬虫就是为了获取这些内容,通过分析和过滤 html 代码,从中获取我们想要资源(文本,图片,视频…..)Python爬虫的原理爬虫的基本流程发起请求通过 HTTP 库向目标站点发起请求,也就是发送一个 Request,请求可以包含额外的 header 等信息,等待服务器响应获取响应内容如果服务器能正常响应,会得到一个 Response,Response 的内容便是所要获取的页面内容,类型可能是 HTML,Json 字符串,二进制数据(图片或者视频)等类型解析内容得到的内容可能是 HTML, 可以用正则表达式,页面解析库进行解析,可能是 Json, 可以直接转换为 Json 对象解析,可能是二进制数据,可以做保存或者进一步的处理保存数据保存形式多样,可以存为文本,也可以保存到数据库,或者保存特定格式的文件什么是 Request,Response浏览器发送消息给网址所在的服务器,这个过程就叫做 HTPP Request服务器收到浏览器发送的消息后,能够根据浏览器发送消息的内容,做相应的处理,然后把消息回传给浏览器,这个过程就是 HTTP Response浏览器收到服务器的 Response 信息后,会对信息进行相应的处理,然后展示Request 中包含什么?请求方式主要有:GET/POST 两种类型常用,另外还有 HEAD/PUT/DELETE/OPTIONSGET 和 POST 的区别就是:请求的数据 GET 是在 url 中,POST 则是存放在头部GET: 向指定的资源发出 “显示” 请求。使用 GET 方法应该只用在读取数据,而不应当被用于产生 “副作用” 的操作中,例如在 Web Application 中。其中一个原因是 GET 可能会被网络蜘蛛等随意访问POST: 向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。HEAD:与 GET 方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中 “关于该资源的信息”(元信息或称元数据)。PUT:向指定资源位置上传其最新内容。OPTIONS:这个方法可使服务器传回该资源所支持的所有 HTTP 请求方法。用 ‘’ 来代替资源名称,向 Web 服务器发送 OPTIONS 请求,可以测试服务器功能是否正常运作。DELETE:请求服务器删除 Request-URI 所标识的资源。请求 URLURL,即统一资源定位符,也就是我们说的网址,统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。URL 的格式由三个部分组成:第一部分是协议 (或称为服务方式)。第二部分是存有该资源的主机 IP 地址 (有时也包括端口号)。第三部分是主机资源的具体地址,如目录和文件名等。爬虫爬取数据时必须要有一个目标的 URL 才可以获取数据,因此,它是爬虫获取数据的基本依据。请求头包含请求时的头部信息,如 User-Agent,Host,Cookies 等信息请求体请求是携带的数据,如提交表单数据时候的表单数据(POST)Response 中包含了什么所有 HTTP 响应的第一行都是状态行,依次是当前 HTTP 版本号,3 位数字组成的状态代码,以及描述状态的短语,彼此由空格分隔。响应状态有多种响应状态,如:200 代表成功,301 跳转,404 找不到页面,502 服务器错误1xx 消息 —— 请求已被服务器接收,继续处理2xx 成功 —— 请求已成功被服务器接收、理解、并接受3xx 重定向 —— 需要后续操作才能完成这一请求4xx 请求错误 —— 请求含有词法错误或者无法被执行5xx 服务器错误 —— 服务器在处理某个正确请求时发生错误 常见代码: 200 OK 请求成功 301 目标永久性转移 302 目标暂时性转移400 Bad Request 客户端请求有语法错误,不能被服务器所理解 401 Unauthorized 请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用 403 Forbidden 服务器收到请求,但是拒绝提供服务 404 Not Found 请求资源不存在,eg:输入了错误的 URL 500 Internal Server Error 服务器发生不可预期的错误 503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常 响应头如内容类型,类型的长度,服务器信息,设置 Cookie响应体最主要的部分,包含请求资源的内容,如网页 HTMl, 图片,二进制数据等能爬取什么样的数据网页文本:如 HTML 文档,Json 格式化文本等图片:获取到的是二进制文件,保存为图片格式视频:同样是二进制文件其他:只要请求到的,都可以获取如何解析数据直接处理Json 解析正则表达式处理BeautifulSoup 解析处理PyQuery 解析处理XPath 解析处理关于抓取的页面数据和浏览器里看到的不一样的问题出现这种情况是因为,很多网站中的数据都是通过 js,ajax 动态加载的,所以直接通过 get 请求获取的页面和浏览器显示的不同。如何解决 js 渲染的问题?分析 ajaxSelenium/webdriverSplashPyV8,Ghost.py怎样保存数据文本:纯文本,Json,Xml 等关系型数据库:如 mysql,oracle,sql server 等结构化数据库非关系型数据库:MongoDB,Redis 等 key-value 形式存储Scrapy简介Scrapy is an application framework for crawling web sites and extracting structured data which can be used for a wide range of useful applications, like data mining, information processing or historical archival.Scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。Scrapy Tutorialhttps://docs.scrapy.org/en/la…Scrapy架构Scrapy Engine引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。 详细内容查看下面的数据流 (Data Flow) 部分。此组件相当于爬虫的 “大脑”,是整个爬虫的调度中心。调度器 (Scheduler)调度器从引擎接受 request 并将他们入队,以便之后引擎请求他们时提供给引擎。初始的爬取 URL 和后续在页面中获取的待爬取的 URL 将放入调度器中,等待爬取。同时调度器会自动去除重复的 URL(如果特定的 URL 不需要去重也可以通过设置实现,如 post 请求的 URL)下载器 (Downloader)下载器负责获取页面数据并提供给引擎,而后提供给 spider。SpidersSpider 是 Scrapy 用户编写用于分析 response 并提取 item (即获取到的 item) 或额外跟进的 URL 的类。 每个 spider 负责处理一个特定 (或一些) 网站。Item PipelineItem Pipeline 负责处理被 spider 提取出来的 item。典型的处理有清理、 验证及持久化 (例如存取到数据库中)。当页面被爬虫解析所需的数据存入 Item 后,将被发送到项目管道 (Pipeline),并经过几个特定的次序处理数据,最后存入本地文件或存入数据库。下载器中间件 (Downloader middlewares)下载器中间件是在引擎及下载器之间的特定钩子 (specific hook),处理 Downloader 传递给引擎的 response。 其提供了一个简便的机制,通过插入自定义代码来扩展 Scrapy 功能。通过设置下载器中间件可以实现爬虫自动更换 user-agent、IP 等功能。Spider 中间件 (Spider middlewares)Spider 中间件是在引擎及 Spider 之间的特定钩子 (specific hook),处理 spider 的输入 (response) 和输出 (items 及 requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展 Scrapy 功能。数据流 (Data flow)引擎打开一个网站 (open a domain),找到处理该网站的 Spider 并向该 spider 请求第一个要爬取的 URL (s)。引擎从 Spider 中获取到第一个要爬取的 URL 并在调度器 (Scheduler) 以 Request 调度。引擎向调度器请求下一个要爬取的 URL。调度器返回下一个要爬取的 URL 给引擎,引擎将 URL 通过下载中间件 (请求 (request) 方向) 转发给下载器 (Downloader)。一旦页面下载完毕,下载器生成一个该页面的 Response,并将其通过下载中间件 (返回 (response) 方向) 发送给引擎。引擎从下载器中接收到 Response 并通过 Spider 中间件 (输入方向) 发送给 Spider 处理。Spider 处理 Response 并返回爬取到的 Item 及 (跟进的) 新的 Request 给引擎。引擎将 (Spider 返回的) 爬取到的 Item 给 Item Pipeline,将 (Spider 返回的) Request 给调度器。(从第二步) 重复直到调度器中没有更多地 request,引擎关闭该网站。Scrapy 爬取豆瓣电影 Top250 榜单https://docs.scrapy.org/en/la…工具和环境语言: Python 3.7IDE: Pycharm爬虫框架:Scrapy浏览器: Google Chrome浏览器插件: XPath Helper创建项目在开始爬取之前,首先要创建一个新的 Scrapy 项目。这里以爬取豆瓣电影 Top250 为例,进入你打算存储代码的目录中,运行下列命令:scrapy startproject douban该命令将会创建包含下列内容的 douban 目录:douban|– init.py|– pycache| |– init.cpython-37.pyc| |– items.cpython-37.pyc| |– pipelines.cpython-37.pyc| -- settings.cpython-37.pyc|-- items.py|-- middlewares.py|-- pipelines.py|-- settings.py– spiders |– init.py |– pycache | |– init.cpython-37.pyc | -- douban_spider.cpython-37.pyc – douban_spider.py3 directories, 13 files这些文件分别是:scrapy.cfg: 项目的配置文件。douban/: 该项目的 python 模块。之后您将在此加入代码。douban/items.py: 项目中的 item 文件。定义我们所要爬取的信息的相关属性。douban/pipelines.py: 项目中的 pipelines 文件。当数据被爬虫爬取下来后,它会被发送到 item pipelines 中,每个 item pipelines 组件(有时称为 “项目管道”)是一个实现简单方法的 Python 类。他们收到一个项目并对其执行操作,还决定该项目是否应该继续通过管道或被丢弃并且不再被处理。douban/settings.py: 项目的设置文件。douban/spiders/: 放置 spider 代码的目录。观察页面结构首先我们打开豆瓣电影 TOP250 的页面,通过观察页面决定让我们的爬虫获取每一部电影的排名、电影名称、评分和评分的人数。https://movie.douban.com/top250运行Chrome F12开发者工具,使用选取工具选取整个电影的信息,可以发现,所有的信息都是放在单独的一个 li 标签中的,而且在 li 下还有一个 class 为 item 的 div 包裹着所有的信息。<li> <div class=“item”> <div class=“pic”> <em class="">1</em> <a href=“https://movie.douban.com/subject/1292052/"> <img width=“100” alt=“肖申克的救赎” src=“https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class=”"> </a> </div> <div class=“info”> <div class=“hd”> <a href=“https://movie.douban.com/subject/1292052/" class=”"> <span class=“title”> 肖申克的救赎</span> <span class=“title”>&nbsp;/&nbsp;The Shawshank Redemption</span> <span class=“other”>&nbsp;/&nbsp;月黑高飞 (港) / 刺激 1995 (台)</span> </a> <span class=“playable”>[可播放]</span> </div> <div class=“bd”> <p class=”"> 导演:弗兰克・德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演:蒂姆・罗宾斯 Tim Robbins /…<br> 1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情 </p> <div class=“star”> <span class=“rating5-t”></span> <span class=“rating_num” property=“v:average”>9.6</span> <span property=“v:best” content=“10.0”></span> <span>1338863 人评价</span> </div> <p class=“quote”> <span class=“inq”>希望让人自由。</span> </p> </div> </div> </div> </li>声明Item什么是 Items 呢?官方文档 Items 定义如下:爬取的主要目标就是从非结构性的数据源提取结构性数据,例如网页。 Scrapy spider 可以以 python 的 dict 来返回提取的数据。虽然 dict 很方便,并且用起来也熟悉,但是其缺少结构性,容易打错字段的名字或者返回不一致的数据,尤其在具有多个 spider 的大项目中。为了定义常用的输出数据,Scrapy 提供了 Item 类。 Item 对象是种简单的容器,保存了爬取到得数据。 其提供了 类似于词典 (dictionary-like) 的 API 以及用于声明可用字段的简单语法。许多 Scrapy 组件使用了 Item 提供的额外信息: exporter 根据 Item 声明的字段来导出数据、 序列化可以通过 Item 字段的元数据 (metadata) 来定义、 trackref 追踪 Item 实例来帮助寻找内存泄露 (see 使用 trackref 调试内存泄露) 等等。Item 使用简单的 class 定义语法以及 Field 对象来声明。我们打开 spider 目录下的 items.py 文件写入下列代码声明 Item:# -- coding: utf-8 --# Define here the models for your scraped items## See documentation in:# https://doc.scrapy.org/en/latest/topics/items.htmlimport scrapyclass DoubanItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() serial_number = scrapy.Field() movie_name = scrapy.Field() introduce = scrapy.Field() star = scrapy.Field() evaluate = scrapy.Field() describe = scrapy.Field()编写爬虫程序在编写代码前我们可以通过修改settings.py文件调整user-agent和其它参数# -- coding: utf-8 --# Scrapy settings for douban project## For simplicity, this file contains only settings considered important or# commonly used. You can find more settings consulting the documentation:## https://doc.scrapy.org/en/latest/topics/settings.html# https://doc.scrapy.org/en/latest/topics/downloader-middleware.html# https://doc.scrapy.org/en/latest/topics/spider-middleware.htmlBOT_NAME = ‘douban’SPIDER_MODULES = [‘douban.spiders’]NEWSPIDER_MODULE = ‘douban.spiders’# Crawl responsibly by identifying yourself (and your website) on the user-agentUSER_AGENT = ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36’# Obey robots.txt rulesROBOTSTXT_OBEY = False# Configure a delay for requests for the same website (default: 0)# See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay# See also autothrottle settings and docsDOWNLOAD_DELAY = 0.5# Configure item pipelines# See https://doc.scrapy.org/en/latest/topics/item-pipeline.htmlITEM_PIPELINES = { ‘douban.pipelines.DoubanPipeline’: 300,}mongo_host = ‘127.0.0.1’mongo_port = 27017mongo_db_name = ‘douban’mongo_db_collection = ‘douban_movie’在 spiders 文件夹下创建 douban_spider.py 文件在我们编写爬虫之前,先了解一下 scrapy 的爬取机制,scrapy 提取数据有自己的一套机制。它们被称作选择器 (seletors),因为他们通过特定的 XPath 或者 CSS 表达式来 “选择” HTML 文件中的某个部分。Xpath 学习教程 http://www.w3school.com.cn/xp...XPath Helperhttps://chrome.google.com/web…Scrapy xpath-tutorialhttps://doc.scrapy.org/en/xpa…# -- coding: utf-8 -*-import scrapyfrom douban.items import DoubanItemclass DoubanSpiderSpider(scrapy.Spider): name = ‘douban_spider’ allowed_domains = [‘movie.douban.com’] start_urls = [‘https://movie.douban.com/top250’] def parse(self, response): movie_list = response.xpath("//div[@class=‘article’]//ol[@class=‘grid_view’]/li") for i_item in movie_list: douban_item = DoubanItem() douban_item[‘serial_number’] = i_item.xpath(".//div[@class=‘item’]//em/text()").extract_first() douban_item[‘movie_name’] = i_item.xpath(".//div[@class=‘info’]/div[@class=‘hd’]/a/span[1]/text()").extract_first() content = i_item.xpath(".//div[@class=‘info’]//div[@class=‘bd’]/p[1]/text()").extract() for i_content in content: content_s = “".join(i_content.split()) douban_item[‘introduce’] = content_s douban_item[‘star’] = i_item.xpath(”.//span[@class=‘rating_num’]/text()").extract_first() douban_item[’evaluate’] = i_item.xpath(".//div[@class=‘star’]//span[4]/text()").extract_first() douban_item[‘describe’] = i_item.xpath(".//p[@class=‘quote’]//span/text()").extract_first() yield douban_item next_link = response.xpath("//span[@class=‘next’]/link/@href").extract() if next_link: next_link = next_link[0] yield scrapy.Request(“https://movie.douban.com/top250"+next_link,callback=self.parse)自动翻页先别急着高兴,你难道没有发现一个问题吗?这样的话我们还是只能爬到当前页的 25 个电影的内容。怎么样才能把剩下的也一起爬下来呢?实现自动翻页一般有两种方法:在页面中找到下一页的地址;自己根据 URL 的变化规律构造所有页面地址。一般情况下我们使用第一种方法,第二种方法适用于页面的下一页地址为 JS 加载的情况。这次我们只说第一种方法。首先利用 Chrome 浏览器的开发者工具找到下一页的地址,然后在解析该页面时获取下一页的地址并将地址交给调度器 (Scheduler)运行爬虫scrapy crawl douban_spiderscrapy crawl douban_spider -o douban.csv(venv) wangao@wangao-MAC  ~/Documents/git/wangao/python3/scrapy/douban  python -VPython 3.7.1(venv) wangao@wangao-MAC  ~/Documents/git/wangao/python3/scrapy/douban  scrapy crawl douban_spider -o douban.csv2019-03-02 15:37:56 [scrapy.utils.log] INFO: Scrapy 1.5.1 started (bot: douban)2019-03-02 15:37:56 [scrapy.utils.log] INFO: Versions: lxml 4.2.5.0, libxml2 2.9.8, cssselect 1.0.3, parsel 1.5.1, w3lib 1.19.0, Twisted 18.9.0, Python 3.7.1 (default, Nov 6 2018, 18:46:03) - [Clang 10.0.0 (clang-1000.11.45.5)], pyOpenSSL 18.0.0 (OpenSSL 1.1.0j 20 Nov 2018), cryptography 2.4.2, Platform Darwin-18.2.0-x86_64-i386-64bit2019-03-02 15:37:56 [scrapy.crawler] INFO: Overridden settings: {‘BOT_NAME’: ‘douban’, ‘DOWNLOAD_DELAY’: 0.5, ‘FEED_FORMAT’: ‘csv’, ‘FEED_URI’: ‘douban.csv’, ‘NEWSPIDER_MODULE’: ‘douban.spiders’, ‘SPIDER_MODULES’: [‘douban.spiders’], ‘USER_AGENT’: ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36’}2019-03-02 15:37:56 [scrapy.middleware] INFO: Enabled extensions:[‘scrapy.extensions.corestats.CoreStats’, ‘scrapy.extensions.telnet.TelnetConsole’, ‘scrapy.extensions.memusage.MemoryUsage’, ‘scrapy.extensions.feedexport.FeedExporter’, ‘scrapy.extensions.logstats.LogStats’]2019-03-02 15:37:56 [scrapy.middleware] INFO: Enabled downloader middlewares:[‘scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware’, ‘scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware’, ‘scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware’, ‘scrapy.downloadermiddlewares.useragent.UserAgentMiddleware’, ‘scrapy.downloadermiddlewares.retry.RetryMiddleware’, ‘scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware’, ‘scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware’, ‘scrapy.downloadermiddlewares.redirect.RedirectMiddleware’, ‘scrapy.downloadermiddlewares.cookies.CookiesMiddleware’, ‘scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware’, ‘scrapy.downloadermiddlewares.stats.DownloaderStats’]2019-03-02 15:37:56 [scrapy.middleware] INFO: Enabled spider middlewares:[‘scrapy.spidermiddlewares.httperror.HttpErrorMiddleware’, ‘scrapy.spidermiddlewares.offsite.OffsiteMiddleware’, ‘scrapy.spidermiddlewares.referer.RefererMiddleware’, ‘scrapy.spidermiddlewares.urllength.UrlLengthMiddleware’, ‘scrapy.spidermiddlewares.depth.DepthMiddleware’]2019-03-02 15:37:56 [scrapy.middleware] INFO: Enabled item pipelines:[‘douban.pipelines.DoubanPipeline’]2019-03-02 15:37:56 [scrapy.core.engine] INFO: Spider opened2019-03-02 15:37:56 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)2019-03-02 15:37:56 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023^C2019-03-02 15:37:56 [scrapy.crawler] INFO: Received SIGINT, shutting down gracefully. Send again to force 2019-03-02 15:37:56 [scrapy.core.engine] INFO: Closing spider (shutdown)2019-03-02 15:37:58 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/top250> (referer: None)2019-03-02 15:37:58 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/top250>{'describe': ‘希望让人自由。’, ’evaluate’: ‘1338863人评价’, ‘introduce’: ‘1994/美国/犯罪剧情’, ‘movie_name’: ‘肖申克的救赎’, ‘serial_number’: ‘1’, ‘star’: ‘9.6’}2019-03-02 15:37:58 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/top250>{'describe': ‘风华绝代。’, ’evaluate’: ‘989216人评价’, ‘introduce’: ‘1993/中国大陆香港/剧情爱情同性’, ‘movie_name’: ‘霸王别姬’, ‘serial_number’: ‘2’, ‘star’: ‘9.6’}2019-03-02 15:37:58 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/top250>{'describe': ‘怪蜀黍和小萝莉不得不说的故事。’, ’evaluate’: ‘1225142人评价’, ‘introduce’: ‘1994/法国/剧情动作犯罪’, ‘movie_name’: ‘这个杀手不太冷’, ‘serial_number’: ‘3’, ‘star’: ‘9.4’}2019-03-02 15:37:58 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/top250>{'describe': ‘一部美国近现代史。’, ’evaluate’: ‘1054616人评价’, ‘introduce’: ‘1994/美国/剧情爱情’, ‘movie_name’: ‘阿甘正传’, ‘serial_number’: ‘4’, ‘star’: ‘9.4’}describe,evaluate,introduce,movie_name,serial_number,star希望让人自由。,1338863人评价,1994/美国/犯罪剧情,肖申克的救赎,1,9.6风华绝代。,989216人评价,1993/中国大陆香港/剧情爱情同性,霸王别姬,2,9.6怪蜀黍和小萝莉不得不说的故事。,1224747人评价,1994/法国/剧情动作犯罪,这个杀手不太冷,3,9.4一部美国近现代史。,1054616人评价,1994/美国/剧情爱情,阿甘正传,4,9.4最美的谎言。,617064人评价,1997/意大利/剧情喜剧爱情战争,美丽人生,5,9.5失去的才是永恒的。 ,993900人评价,1997/美国/剧情爱情灾难,泰坦尼克号,6,9.3最好的宫崎骏,最好的久石让。 ,981959人评价,2001/日本/剧情动画奇幻,千与千寻,7,9.3拯救一个人,就是拯救整个世界。,550815人评价,1993/美国/剧情历史战争,辛德勒的名单,8,9.5诺兰给了我们一场无法盗取的梦。,1067442人评价,2010/美国英国/剧情科幻悬疑冒险,盗梦空间,9,9.3结尾Scrapy 爬虫框架掌握好可以事半功倍,但是遇到简单的需求未必需要使用框架去解决。关于IP代理中间件,写入数据库,Web前台展示等需求都是非常值得延伸的内容,希望大家通过爬虫豆瓣电影Top250这个入门项目开个学习的好头。 ...

March 7, 2019 · 6 min · jiezi

LogParser v0.8.0 发布:一个用于定期增量式解析 Scrapy 爬虫日志的 Python 库

GitHub 开源my8100 / logparser安装通过 pip:pip install logparser通过 git:git clone https://github.com/my8100/logparser.gitcd logparserpython setup.py install使用方法作为 service 运行请先确保当前主机已经安装和启动 Scrapyd通过命令 logparser 启动 LogParser访问 http://127.0.0.1:6800/logs/stats.json (假设 Scrapyd 运行于端口 6800)访问 http://127.0.0.1:6800/logs/projectname/spidername/jobid.json 以获取某个爬虫任务的日志分析详情配合 ScrapydWeb 实现爬虫进度可视化详见 my8100 / scrapydweb在 Python 代码中使用In [1]: from logparser import parseIn [2]: log = “““2018-10-23 18:28:34 [scrapy.utils.log] INFO: Scrapy 1.5.0 started (bot: demo) …: 2018-10-23 18:29:41 [scrapy.statscollectors] INFO: Dumping Scrapy stats: …: {‘downloader/exception_count’: 3, …: ‘downloader/exception_type_count/twisted.internet.error.TCPTimedOutError’: 3, …: ‘downloader/request_bytes’: 1336, …: ‘downloader/request_count’: 7, …: ‘downloader/request_method_count/GET’: 7, …: ‘downloader/response_bytes’: 1669, …: ‘downloader/response_count’: 4, …: ‘downloader/response_status_count/200’: 2, …: ‘downloader/response_status_count/302’: 1, …: ‘downloader/response_status_count/404’: 1, …: ‘dupefilter/filtered’: 1, …: ‘finish_reason’: ‘finished’, …: ‘finish_time’: datetime.datetime(2018, 10, 23, 10, 29, 41, 174719), …: ‘httperror/response_ignored_count’: 1, …: ‘httperror/response_ignored_status_count/404’: 1, …: ‘item_scraped_count’: 2, …: ’log_count/CRITICAL’: 5, …: ’log_count/DEBUG’: 14, …: ’log_count/ERROR’: 5, …: ’log_count/INFO’: 75, …: ’log_count/WARNING’: 3, …: ‘offsite/domains’: 1, …: ‘offsite/filtered’: 1, …: ‘request_depth_max’: 1, …: ‘response_received_count’: 3, …: ‘retry/count’: 2, …: ‘retry/max_reached’: 1, …: ‘retry/reason_count/twisted.internet.error.TCPTimedOutError’: 2, …: ‘scheduler/dequeued’: 7, …: ‘scheduler/dequeued/memory’: 7, …: ‘scheduler/enqueued’: 7, …: ‘scheduler/enqueued/memory’: 7, …: ‘start_time’: datetime.datetime(2018, 10, 23, 10, 28, 35, 70938)} …: 2018-10-23 18:29:42 [scrapy.core.engine] INFO: Spider closed (finished)“““In [3]: d = parse(log, headlines=1, taillines=1)In [4]: dOut[4]:OrderedDict([(‘head’, ‘2018-10-23 18:28:34 [scrapy.utils.log] INFO: Scrapy 1.5.0 started (bot: demo)’), (’tail’, ‘2018-10-23 18:29:42 [scrapy.core.engine] INFO: Spider closed (finished)’), (‘first_log_time’, ‘2018-10-23 18:28:34’), (’latest_log_time’, ‘2018-10-23 18:29:42’), (’elapsed’, ‘0:01:08’), (‘first_log_timestamp’, 1540290514), (’latest_log_timestamp’, 1540290582), (‘datas’, []), (‘pages’, 3), (‘items’, 2), (’latest_matches’, {‘resuming_crawl’: ‘’, ’latest_offsite’: ‘’, ’latest_duplicate’: ‘’, ’latest_crawl’: ‘’, ’latest_scrape’: ‘’, ’latest_item’: ‘’, ’latest_stat’: ‘’}), (’latest_crawl_timestamp’, 0), (’latest_scrape_timestamp’, 0), (’log_categories’, {‘critical_logs’: {‘count’: 5, ‘details’: []}, ’error_logs’: {‘count’: 5, ‘details’: []}, ‘warning_logs’: {‘count’: 3, ‘details’: []}, ‘redirect_logs’: {‘count’: 1, ‘details’: []}, ‘retry_logs’: {‘count’: 2, ‘details’: []}, ‘ignore_logs’: {‘count’: 1, ‘details’: []}}), (‘shutdown_reason’, ‘N/A’), (‘finish_reason’, ‘finished’), (’last_update_timestamp’, 1547559048), (’last_update_time’, ‘2019-01-15 21:30:48’)])In [5]: d[’elapsed’]Out[5]: ‘0:01:08’In [6]: d[‘pages’]Out[6]: 3In [7]: d[‘items’]Out[7]: 2In [8]: d[‘finish_reason’]Out[8]: ‘finished’ ...

January 24, 2019 · 2 min · jiezi

使用Scrapy抓取优酷视频列表页(电影/电视)

具体代码可参看Knowsmore这里列表页是指PC端的入口,如电影抓取后数据如下:{ “link” : “//v.youku.com/v_show/id_XMzMyMzE2MTMxNg==.html”, “thumb_img” : “http://r1.ykimg.com/051600005AD944F0859B5E040E03BD62", “title” : “大毛狗”, “tag” : [ “VIP” ], “actors” : [ “何明翰”, “张璇” ], “play_times” : " 历史 2,236万次播放 “}# -- coding: utf-8 --import scrapyimport reimport jsonfrom scrapy import Selector, Requestfrom knowsmore.items import YoukuListItemfrom ..common import *from ..model.mongodb import *class YoukuListSpider(scrapy.Spider): name = “youku_list” custom_settings = { ‘DOWNLOADER_MIDDLEWARES’ : { } } start_urls = [ ‘https://list.youku.com/category/show/c_96_s_1_d_4_p_29.html’ ] def parse(self, response): GRID_SELECTOR = ‘.panel .mr1’ for grid in response.css(GRID_SELECTOR): THUMB_IMG_SELECTOR = ‘.p-thumb img::attr(_src)’ LINK_SELECTOR = ‘.info-list .title a::attr(href)’ TITLE_SELECTOR = ‘.info-list .title a::text’ ACTORS_SELECTOR = ‘.info-list .actor a::text’ TAG_SELECTOR = ‘.p-thumb .p-thumb-tagrt span::text’ PLAY_TIMES_SELECTOR = ‘.info-list li:nth-child(3)::text’ item_thumb_img = grid.css( THUMB_IMG_SELECTOR).extract_first() item_link = grid.css( LINK_SELECTOR).extract_first() item_title = grid.css( TITLE_SELECTOR).extract_first() item_actors = grid.css( ACTORS_SELECTOR).extract() item_tag = grid.css( TAG_SELECTOR).extract() item_play_times = grid.css( PLAY_TIMES_SELECTOR).extract_first() # Build Scrapy Item youku_item = YoukuListItem( thumb_img = item_thumb_img, link = item_link, title = item_title, actors = item_actors, play_times = item_play_times, tag = item_tag ) # Send to Pipelines yield youku_item NEXT_PAGE_SELECTOR = ‘.yk-pages .next a::attr(href)’ next_page = response.css(NEXT_PAGE_SELECTOR).extract_first() if next_page is not None: print next_page yield response.follow(next_page) ...

January 10, 2019 · 1 min · jiezi

使用scrapy抓取Youtube播放页数据

可参看Knowsmore抓取Youtube播放页数据的前提是scrapy部署的机器可以正常访问Youtube网站示例网址抓取的原理是读取Youtube播放页桌面版网页源代码中的全局变量: ytInitialData存取到Mongo中的数据如下:{ “title” : “20130410 锵锵三人行 陈平原谈中国教育问题”, “view_count” : “12,407 views”}代码如下:# -- coding: utf-8 --import scrapyimport reimport jsonfrom scrapy import Selectorfrom knowsmore.items import YoutubeItemfrom ..common import class YoutubeSpider(scrapy.Spider): custom_settings = { ‘DOWNLOADER_MIDDLEWARES’ : { } } name = ‘youtube’ allowed_domains = [‘www.youtube.com’] start_urls = [‘https://www.youtube.com/watch?v=3vkqOdMBP48’] def parse(self, response): ytInitialData = r1(r’ytInitialData"] = (.?)}};’, response.body) if ytInitialData: ytInitialData = ‘%s}}’ % ytInitialData ytInitialDataObj = json.loads(ytInitialData) videoInfo = ytInitialDataObj[‘contents’][’twoColumnWatchNextResults’][‘results’][‘results’][‘contents’][0][‘videoPrimaryInfoRenderer’] Item = YoutubeItem( title = videoInfo[’title’][‘simpleText’].encode(‘utf-8’), view_count = videoInfo[‘viewCount’][‘videoViewCountRenderer’][‘viewCount’][‘simpleText’] ) yield Item ...

January 9, 2019 · 1 min · jiezi

使用scrapy抓取Youtube播放列表信息

可参看Knowsmore抓取Youtube列表数据的前提是scrapy部署的机器可以正常访问Youtube网站示例网址存取到Mongo中的数据如下:{ “playlist_id” : “PLEbPmOCXPYV67l45xFBdmodrPkhzuwSe9”, “videos” : [ { “playlist_id” : “PLEbPmOCXPYV67l45xFBdmodrPkhzuwSe9”, “video_id” : “9pTwztLOvj4”, “thumbnail” : [ { “url” : “https://i.ytimg.com/vi/9pTwztLOvj4/hqdefault.jpg?sqp=-oaymwEZCPYBEIoBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLCmUXUPe-HgXiie0SRfL5cYz0JRrg”, “width” : 245, “height” : 137 } ], “title” : “Legend of the galactic heroes (1988) episode 1”, “index” : 1, “length_seconds” : 1445, “is_playable” : true }, { “playlist_id” : “PLEbPmOCXPYV67l45xFBdmodrPkhzuwSe9”, “video_id” : “zzD1xU37Vtc”, “thumbnail” : [ { “url” : “https://i.ytimg.com/vi/zzD1xU37Vtc/hqdefault.jpg?sqp=-oaymwEZCPYBEIoBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLCnLCYaZVBeHnZR0T73rfEd_Dbyew”, “width” : 245, “height” : 137 } ], “title” : “Legend of the galactic heroes (1988) episode 2”, “index” : 2, “length_seconds” : 1447, “is_playable” : true },代码如下:# -- coding: utf-8 --import scrapyimport reimport jsonfrom scrapy import Selectorfrom knowsmore.items import YoutubePlaylistItem, YoutubePlaylistVideoItemfrom ..common import class YoutubeListSpider(scrapy.Spider): name = ‘youtube_list’ allowed_domains = [‘www.youtube.com’] start_urls = [‘https://www.youtube.com/playlist?list=PLEbPmOCXPYV67l45xFBdmodrPkhzuwSe9’] def parse(self, response): # Extract JSON Data with Regex Expression ytInitialData = r1(r’window[“ytInitialData”] = (.?)}};’, response.body) if ytInitialData: ytInitialData = ‘%s}}’ % ytInitialData ytInitialDataObj = json.loads(ytInitialData) # Assign VideoList info to variable playListInfo = ytInitialDataObj[‘contents’][’twoColumnBrowseResultsRenderer’][’tabs’][0][’tabRenderer’][‘content’][‘sectionListRenderer’][‘contents’][0][‘itemSectionRenderer’][‘contents’][0][‘playlistVideoListRenderer’] # Build Scrapy Item playList = YoutubePlaylistItem( playlist_id = playListInfo[‘playlistId’], videos = [] ) # Insert the videoItem to YoutubePlaylistItem videos field for videoInfo in playListInfo[‘contents’]: videoInfo = videoInfo[‘playlistVideoRenderer’] videoItem = YoutubePlaylistVideoItem( playlist_id = playListInfo[‘playlistId’], video_id = videoInfo[‘videoId’], thumbnail = videoInfo[’thumbnail’][’thumbnails’], title = videoInfo[’title’][‘simpleText’], index = videoInfo[‘index’][‘simpleText’], length_seconds = videoInfo[’lengthSeconds’], is_playable = videoInfo[‘isPlayable’] ) playList[‘videos’].append(videoItem) yield playList ...

January 8, 2019 · 1 min · jiezi

使用Scrapy抓取新浪微博用户信息

详细代码可查看Knowsmore数据的来源是新浪微博的手机端H5页面个人资料API:https://m.weibo.cn/profile/in…【用户ID】发出的微博API:https://m.weibo.cn/api/contai…【用户ID】_-WEIBO_SECOND_PROFILE_WEIBO&page_type=03&page=【页数从1开始】# -- coding: utf-8 --import scrapyimport reimport jsonimport os,sysfrom scrapy import Selector, Requestfrom knowsmore.items import WeiboUserItem, WeiboStatusItemfrom ..common import *from ..model.mongodb import *WEIBO_USER_CONFIG = { ‘BASE_URL’ : ‘https://m.weibo.cn’, ‘USER_IDS’ : [‘6883966016’]}class WeiboUserSpider(scrapy.Spider): name = “weibo_user” def start_requests(self): for uid in WEIBO_USER_CONFIG[‘USER_IDS’]: url = ‘%s/profile/info?uid=%s’ % (WEIBO_USER_CONFIG[‘BASE_URL’], uid) yield Request(url) # Define your statuses implementation here, just a demo below for i in range(1, 2): status_url = ‘%s/api/container/getIndex?containerid=230413%s-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&page=%d’ % (WEIBO_USER_CONFIG[‘BASE_URL’], uid, i) yield Request(status_url, callback=self.parse_status) # https://m.weibo.cn/profile/1784537661 def parse(self, response): user_data = json.loads(response.text) yield WeiboUserItem( fans_url = user_data[‘data’][‘fans’], follow_url = user_data[‘data’][‘follow’], more_url = user_data[‘data’][‘more’], user = user_data[‘data’][‘user’] ) # https://m.weibo.cn/api/container/getIndex?containerid=2304131784537661_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&page=2 def parse_status(self, response): status_data = json.loads(response.text) yield WeiboStatusItem( cards = status_data[‘data’][‘cards’] ) ...

January 7, 2019 · 1 min · jiezi

Scrapy-实用的命令行工具实现方法

其实这篇文章是scrapy源码学习的(一),加载器那篇才是(二)scrapy的命令行工具本文环境:wind7 64bitspython 3.7scrapy 1.5.1scrapy拥有非常灵活的低耦合的命令行工具,如果自己想要重新实现覆盖掉scrapy自带的命令也是可以的。使用它的命令行工具可以大致分为两种情况:在创建的project路径下不在project路径下先看下不在scrapy项目路径下的命令行有哪些:Scrapy 1.5.1 - no active projectUsage: scrapy <command> [options] [args]Available commands: bench Run quick benchmark test fetch Fetch a URL using the Scrapy downloader genspider Generate new spider using pre-defined templates runspider Run a self-contained spider (without creating a project) settings Get settings values shell Interactive scraping console startproject Create new project version Print Scrapy version view Open URL in browser, as seen by Scrapy [ more ] More commands available when run from project directoryUse “scrapy <command> -h” to see more info about a command在项目路径下的命令行新增了check、crawl、edit、list、parse这些命令,具体:Scrapy 1.5.1 - project: myspider01Usage: scrapy <command> [options] [args]Available commands: bench Run quick benchmark test check Check spider contracts crawl Run a spider edit Edit spider fetch Fetch a URL using the Scrapy downloader genspider Generate new spider using pre-defined templates list List available spiders parse Parse URL (using its spider) and print the results runspider Run a self-contained spider (without creating a project) settings Get settings values shell Interactive scraping console startproject Create new project version Print Scrapy version view Open URL in browser, as seen by ScrapyUse “scrapy <command> -h” to see more info about a command也即是说scrapy可以根据当前路径是否是scrapy项目路径来判断提供可用的命令给用户。创建一个scrapy项目在当前路径下创建一个scrapy项目,DOS下输入:scrapy startproject myproject可以查看刚刚创建的项目myproject的目录结构:├── scrapy.cfg //scrapy项目配置文件├── myproject ├── spiders // 爬虫脚本目录 ├── init.py ├── init.py ├── items.py ├── middlewares.py ├── pipelines.py ├── settings.py // 项目设置 可以断定,在我们使用"startproject"这个scrapy命令时,scrapy会把一些项目默认模板拷贝到我们创建项目的路径下,从而生成我们看到的类似上面的目录结构。我们可以打开scrapy的包,看看这些模板在哪个地方。切换至scrapy的安装路径(比如:..Python37Libsite-packagesscrapy),可以看到路径下有templates文件夹,而此文件夹下的project文件夹便是创建项目时拷贝的默认模板存放目录。那么scrapy是怎么实现类似“startproject”这样的命令的呢?打开scrapy源码找到入口scrapy是使用命令行来启动脚本的(当然也可以调用入口函数来启动),查看其命令行实现流程必须先找到命令行实行的入口点,这个从其安装文件setup.py中找到。打开setup.py 找到entry_points:… entry_points={ ‘console_scripts’: [‘scrapy = scrapy.cmdline:execute’] },…可以看到scrapy开头的命令皆由模块scrapy.cmdline的execute函数作为入口函数。分析入口函数先浏览一下execute函数源码,这里只贴主要部分:def execute(argv=None, settings=None): if argv is None: argv = sys.argv … #主要部分:获取当前项目的设置 if settings is None: settings = get_project_settings() # set EDITOR from environment if available try: editor = os.environ[‘EDITOR’] except KeyError: pass else: settings[‘EDITOR’] = editor #检查提醒已不被支持的设置项目 check_deprecated_settings(settings) … #主要部分:判断是否在项目路径下,加载可见命令,解析命令参数 inproject = inside_project() cmds = _get_commands_dict(settings, inproject) cmdname = _pop_command_name(argv) parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(), \ conflict_handler=‘resolve’) if not cmdname: _print_commands(settings, inproject) sys.exit(0) elif cmdname not in cmds: _print_unknown_command(settings, cmdname, inproject) sys.exit(2) cmd = cmds[cmdname] parser.usage = “scrapy %s %s” % (cmdname, cmd.syntax()) parser.description = cmd.long_desc() settings.setdict(cmd.default_settings, priority=‘command’) cmd.settings = settings cmd.add_options(parser) opts, args = parser.parse_args(args=argv[1:]) _run_print_help(parser, cmd.process_options, args, opts) cmd.crawler_process = CrawlerProcess(settings) _run_print_help(parser, _run_command, cmd, args, opts) sys.exit(cmd.exitcode)阅读cmdline.py的execute函数,大概了解了命令行实现的基本流程:1.获取命令参数命令参数的获取可以通过两种方式传递:第一种是调用execute,比如:from scrapy.cmdline import executeexecute(argv=[‘scrapy’,‘startproject’,‘myproject’,’-a’,‘xxxx’])这样就相当于第二种方式:命令控制台执行scrapy startproject myproject -a xxxx传递的参数都是[‘scrapy’,‘startproject’,‘myproject’,’-a’,‘xxxx’]2.获取scrapy项目配置如果当前不是调用的方式传递settings给execute入口,而是一般的命令控制台启动scrapy,那么scrapy会在当前路径下搜索加载可能存在的项目配置文件。主要是通过函数get_project_settings执行。ENVVAR = ‘SCRAPY_SETTINGS_MODULE’def get_project_settings(): #获取配置 if ENVVAR not in os.environ: #初始化获取项目的default级配置,即是scrapy生成的默认配置 project = os.environ.get(‘SCRAPY_PROJECT’, ‘default’) #初始化项目环境,设置系统环境变量SCRAPY_SETTINGS_MODULE的值为配置模块路径 init_env(project) settings = Settings() settings_module_path = os.environ.get(ENVVAR) if settings_module_path: settings.setmodule(settings_module_path, priority=‘project’) … return settings获取的配置文件主要是scrapy.cfg,我们可以看下他的内容:[settings]default = myproject.settings[deploy]#url = http://localhost:6800/project = myproject在生成项目myproject的时候,这个配置文件就已经指定了项目设置模块的路径"myproject.settings",所以上面的get_project_settings函数获取便是配置文件settings字段中的default键值,然后导入该设置模块来生成配置。具体实现在init_env函数中。def init_env(project=‘default’, set_syspath=True): “““在当前项目路径下初始化项目环境. 并且通过配置系统环境来让python能够定位配置模块 "”” #在项目路径下进入命令行,才能准确获取配置 #获取可能存在scrapy.cfg配置文件的模块路径 cfg = get_config() #获取到配置文件后设置系统环境变量SCRAPY_SETTINGS_MODULE为配置模块路径, #如: myproject.settings,默认项目级别均为default,即是配置文件字段settings中的键 if cfg.has_option(‘settings’, project): os.environ[‘SCRAPY_SETTINGS_MODULE’] = cfg.get(‘settings’, project) #将最近的scrapy.cfg模块路径放入系统路径使Python能够找到该模块导入 closest = closest_scrapy_cfg() if closest: projdir = os.path.dirname(closest) if set_syspath and projdir not in sys.path: #加入项目设置模块路径到系统路径让Python能够定位到 sys.path.append(projdir)def get_config(use_closest=True): "”" SafeConfigParser.read(filenames) 尝试解析文件列表,如果解析成功返回文件列表。如果filenames是string或Unicode string, 将会按单个文件来解析。如果在filenames中的文件不能打开,该文件将被忽略。这样设计的目的是, 让你能指定本地有可能是配置文件的列表(例如,当前文件夹,用户的根目录,及一些全系统目录), 所以在列表中存在的配置文件都会被读取。""" sources = get_sources(use_closest) cfg = SafeConfigParser() cfg.read(sources) return cfgdef get_sources(use_closest=True): ‘‘‘先获取用户的根目录,及一些全系统目录下的有scrapy.cfg的路径加入sources 最后如果使用最靠近当前路径的scrapy.cfg的标志use_closest为True时加入该scrapy.cfg路径’’’ xdg_config_home = os.environ.get(‘XDG_CONFIG_HOME’) or \ os.path.expanduser(’/.config’) sources = [’/etc/scrapy.cfg’, r’c:\scrapy\scrapy.cfg’, xdg_config_home + ‘/scrapy.cfg’, os.path.expanduser(’/.scrapy.cfg’)] if use_closest: sources.append(closest_scrapy_cfg()) return sourcesdef closest_scrapy_cfg(path=’.’, prevpath=None): """ 搜索最靠近当前当前路径的scrapy.cfg配置文件并返回其路径。 搜索会按照当前路径–>父路径的递归方式进行,到达顶层没有结果则返回‘’ """ if path == prevpath: return ’’ path = os.path.abspath(path) cfgfile = os.path.join(path, ‘scrapy.cfg’) if os.path.exists(cfgfile): return cfgfile return closest_scrapy_cfg(os.path.dirname(path), path)通过init_env来设置os.environ[‘SCRAPY_SETTINGS_MODULE’]的值,这样的话#将项目配置模块路径设置进系统环境变量os.environ[‘SCRAPY_SETTINGS_MODULE’] = ‘myproject.settings’初始化后返回到原先的get_project_settings,生成一个设置类Settings实例,然后再将设置模块加载进实例中完成项目配置的获取这一动作。3.判断是否在scrapy项目路径下判断当前路径是否是scrapy项目路径,其实很简单,因为前面已经初始化过settings,如果在项目路径下,那么os.environ[‘SCRAPY_SETTINGS_MODULE’]的值就已经被设置了,现在只需要判断这个值是否存在便可以判断是否在项目路径下。具体实现在inside_project函数中实现:def inside_project(): scrapy_module = os.environ.get(‘SCRAPY_SETTINGS_MODULE’) if scrapy_module is not None: try: import_module(scrapy_module) except ImportError as exc: warnings.warn(“Cannot import scrapy settings module %s: %s” % (scrapy_module, exc)) else: return True return bool(closest_scrapy_cfg())4.获取命令集合,命令解析知道了当前是否在项目路径下,还有初始化了项目配置,这个时候就可以获取到在当前路径下能够使用的命令行有哪些了。获取当前可用命令集合比较简单,直接加载模块scrapy.commands下的所有命令行类,判断是否需要在项目路径下才能使用该命令,是的话直接实例化加入一个字典(格式:<命令名称>:<命令实例>)返回,具体实现通过_get_commands_dict:def _get_commands_dict(settings, inproject): cmds = _get_commands_from_module(‘scrapy.commands’, inproject) cmds.update(_get_commands_from_entry_points(inproject)) #如果有新的命令行模块在配置中设置,会自动载入 cmds_module = settings[‘COMMANDS_MODULE’] if cmds_module: cmds.update(_get_commands_from_module(cmds_module, inproject)) return cmdsdef _get_commands_from_module(module, inproject): d = {} for cmd in _iter_command_classes(module): #判断是否需要先创建一个项目才能使用该命令, #即目前是否位于项目路径下(inproject)的可用命令有哪些,不是的有哪些 if inproject or not cmd.requires_project: cmdname = cmd.module.split(’.’)[-1] #获取该命令名称并实例化 加入返回字典 #返回{<命令名称>:<命令实例>} d[cmdname] = cmd() return d def _iter_command_classes(module_name): #获取scrapy.commands下所有模块文件中属于ScrapyCommand子类的命令行类 for module in walk_modules(module_name): for obj in vars(module).values(): if inspect.isclass(obj) and \ issubclass(obj, ScrapyCommand) and \ obj.module == module.name and \ not obj == ScrapyCommand: yield obj其中判断是否是命令类的关键在于该命令模块中的命令类是否继承了命令基类ScrapyCommand,只要继承了该基类就可以被检测到。这有点类似接口的作用,ScrapyCommand基类其实就是一个标识类(该类比较简单,可以查看基类代码)。而该基类中有一个requires_project标识,标识是否需要在scrapy项目路径下才能使用该命令,判断该值就可以获得当前可用命令。获取到了可用命令集合,接下来会加载Python自带的命令行解析模块optparser.OptionParser的命令行参数解析器,通过实例化获取该parser,传入当前命令实例的add_options属性方法中来加载当前命令实例附加的解析命令,如:-a xxx, -p xxx, –dir xxx 之类的类似Unix命令行的命令。这些都是通过parser来实现解析。5.判断当前命令是否可用其实在加载解析器之前,会去判断当前的用户输入命令是否是合法的,是不是可用的,如果可用会接下去解析执行该命令,不可用便打印出相关的帮助提示。比如:Usage===== scrapy startproject <project_name> [project_dir]Create new projectOptions=======–help, -h show this help message and exitGlobal Options—————-logfile=FILE log file. if omitted stderr will be used–loglevel=LEVEL, -L LEVEL log level (default: DEBUG)–nolog disable logging completely–profile=FILE write python cProfile stats to FILE–pidfile=FILE write process ID to FILE–set=NAME=VALUE, -s NAME=VALUE set/override setting (may be repeated)–pdb enable pdb on failure至此,scrapy命令行工具的实现流程基本结束。学习点scrapy的命令行工具实现了低耦合,需要删减增加哪个命令行只需要在scrapy.commands模块中修改增删就可以实现。但是实现的关键在于该模块下的每一个命令行类都得继承ScrapyCommand这个基类,这样在导入的时候才能有所判断,所以我说ScrapyCommand是个标识类。基于标识类来实现模块的低耦合。下一篇将会记录根据借鉴scrapy命令行工具实现方法来实现自己的命令行 ...

November 21, 2018 · 3 min · jiezi

2018年 scrapy 安装中文教程

安装指南None 安装Scrapy None Scrapy在CPython(默认Python实现)和PyPy(从PyPy 5.9开始)下运行Python 2.7和Python 3.4或更高版本。 如果您使用的是Anaconda或Miniconda,您可以从conda- forge通道安装该软件包,该软件包含适用于Linux,Windows和OS X的最新软件包。 要使用安装Scrapy conda,请运行: conda install -c conda-forge scrapy 或者,如果您已经熟悉Python包的安装,则可以使用以下命令从PyPI安装Scrapy及其依赖项: pip install Scrapy 国内用户使用豆瓣源加速下载 pip install Scrapy -i https://pypi.douban.com/simple 请注意,有时这可能需要根据您的操作系统解决某些Scrapy依赖项的编译问题,因此请务必查看特定于 平台的安装说明。 ...

September 19, 2018 · 6 min · jiezi