第一周

302 阅读9分钟

request

  • 更简洁更友好
  • 继承了urllib的所有特征
  • 底层用的urllib3
  • get请求
    • requests.get()
    • requests.request("get",url)
    • 可以带有headers和parmas参数
  • post
    • rsp = requests.post(url,data=data)
    • data,headers要求 是dict类型
  • proxy
    • 代理有可能报错,如果使用人数多,考虑网络安全问题,可能会被强行关闭

xpath

  • 在XML文件中查找信息的一套规则/语言,根据XML的元素或者属性进行遍历
  • XML中选取节点
    • nodename:选取此节点的所有子节点
    • /:从根节点开始选取
    • //:选取节点,不考虑位置
    • .:选取当前的节点
    • ..:选取当前节点的父节点
    • @:选取属性
  • XPath中查找一般按照路径方法查找

scrapy概述

  • 包含各个部件
    • scrapyengine:神经中枢,大脑,核心
    • scheduler调度器:引擎发来的request请求,调度器需要处理,然后交换引擎
    • Downloader下载器:把引擎发来的requests发出请求,得到response
    • spider爬虫:负责把下载器得到的网页/结果进行分解,分解成数据+连接
    • itempipeline管道:详细处理item
    • Downloadermiddleware下载中间件:自定义下载的功能扩展组件
    • spidermiddleware爬虫中间件:对spider进行功能扩展
  • 爬虫的大概流程
    • 新建项目:scrapy startproject xxx
    • 明确需要目标:编写item.py
    • 制作爬虫:地址spider/xxspider.py
    • 存储内容:pipelines.py

item封装数据

  • item基类:自定义数据类的基类
  • field类:用来描述自定义数据类包含哪些字段
  • fie元数据
    • 传递额外信息给处理大户局的某个组件,告诉组件应以怎样的方式处理数据
  • 自定义一个数据类,只需继承Item,并创建一系列Field对象的类属性

itempipeline处理数据

  • 对应的是pipelines文件
  • 爬虫提取出数据存入item后,item中保存的数据需要进行一步处理,比如清洗数据,验证数据有效性,过滤掉重复数据,存储数据等
  • pipeline需要处理process_item函数
    • process_item:
      • spider提取出来的item作为参数传入,同时传入的还有spider(爬取此项数据的spider对象)
      • 此方法必须出现,用来处理每一项由spider爬取到的数据
      • 必须返回一个item对象,被丢弃的item不会被之后的pipeline处理
        • 如果process_item在处理某项item时返回了一项数据(Item或字典),返回的数据会递送给下一级Item Pipeline(如果有)继续处理
        • 如果process_item在处理某项item时抛出(raise)一个DropItem异常(scrapy.exceptions.DropItem),该项item便会被抛弃,不再递送给后面的Item Pipeline继续处理,也不会导出到文件,通常,我们在检测到无效数据或想要过滤数据时,抛出DropItem异常
  • __ init __:构造函数
    • 进行一些参数的初始化
  • open_spider(spider)
    • spider对象被开启的时候调用
  • close_spider(spider)
    • 当spider对象被关闭的时候调用
  • from_crawler(cls,crawler)
    • 创建Item Pipeline对象时回调该类方法。通常,在该方法中通过crawler.settings读取配置,根据配置创建Item_Pipeline对象
  • 启用item_pipeline
    • 需要在setting.py中进行配置

spider

  • 对应的是spiders下的文件

  • ___ init __:初始化爬虫列表,start_urls列表

  • start_requests:生成requests对象交给scrapy下载器返回response

  • parse:根据返回的response解析出相应的item,item自动进入pipeline:如果需要,解析出url,url自动交给requests模块,一直循环下去、

  • start_request:此方法只能被调用一次,读取start_urls内容并启动循环过程

  • name:设置爬虫名称,是一个标识

  • start_urls:设置开始的第一批爬虫的url,通常被实现成一个列表

    • 怎样暗中构造并提交的requset对象
    • spider的源码:

    class Spider(object_ref): ... def start_requests(self): for url in self.start_urls: yield self.make_requests_from_url(url)

      def make_requests_from_url(self, url):
          return Request(url, dont_filter=True)
           
      def parse(self, response):
          raise NotImplementedError
      ...
    
    • scrapy引擎调用start_requsets方法,对爬取列表进行迭代,用迭代出的每个url作为参数调用make_requests_from_url方法,然后得到真正的requset对象
    • 我们也可以自己定义start-requse方法
  • allow_domains:spider允许爬取的域名列表

  • start_request(self):只被调用一次

  • parse

    • 实现页面解析函数
    • 使用选择器提取页面中的数据,将数据封装后(item或者字典)提交给引擎
    • 使用选择器或者linkextractor提取页面中的链接,用其构造新的requ对象并提交给scrapy引擎
  • log:日志记录

用LinkExtractor提取链接

  • 提取链接可以使用selector和LinkExtractor两种方法
  • selector:因为链接也是页面中的数据,所以可以使用与提取数据相同的方法进行提取,在提取少量(几个)链接或提取规则比较简单时,使用 Selector就足够了
  • LinkExtractor:在提取大量链接或提取规则比较复杂

中间件(Downloadermiddlewares)

  • 中间件是处于引擎和下载器中间的一层组件

  • 可以有很多个,按顺序加载执行

  • 作用是对发出的请求和返回的结果进行预处理

  • 在middlewares文件中

  • 需要在settings中设置以便生效

  • 编写中间件,必须是scrapy,contrib,Downloadermiddlewar的子类

  • 一般一个中间件完成一项功能

  • 必须实现以下一个或者多个方法

    • process_request(self,request,spider)
      • 在request通过的时候调用
      • 必须返回None或response或者raise ignorerequest
      • None:scrapy将继续处理该request
      • request:scrapy会停止调用process_request并冲洗调度返回的request
      • response:scrapy将不会调用其他的process_request或者process_exception,直接将该response作为结果返回,同时会调用process_response函数
    • process_response(self,request,response,spider)
      • 跟process_response大同小异
      • 每次返回结果的时候自动调用
      • 可以有多个,按顺序调用
  • 去重

    • 为了防止爬虫进入死循环,需要去重
    • 即在spider中的parse函数中,返回request的时候加上dont_filter=False参数

    myspider(scrapy.spider) def parse(……): …… yield screapy.Request(url=url,callback=self.parse,dont_filter=False)

  • 如何在scrapy使用selenium

    • 可以放入中间件中的process_request函数中
    • 在函数中调用selenium,完成爬取后返回response

    class MyMiddleWare(object): def process_request(……): driver = wedriver.Chrome() html = driver,page_source driver.quit() return HtmlResponse(url=url,encoding='utf_8',ody=html,request=request)

scrapy-shell

  • shell
    • 启动:Aanconda Promot(scrapy shell "url:xxx")
    • 启动后自动下载指定的url的网页
    • 下载完后,url的内容保存在response的变量中去,我们需要调用response
  • response
    • 爬取到的内容保存在response中
    • response.body是网页的代码
    • response.headers是返回的http的头信息
    • response.xpath()允许使用xpath语法选择内容
    • response.css()允许使用css语法选取内容
  • selector
    • 选择器,允许用户使用选择器来选择自己想要的内容
    • response.selector.xpath:response.xpath是selector.xpath的快捷方式
    • response.selector.css:response.css是他的快捷方式
    • selector.extract:把节点的内容用Unicode形式返回。extract方法内部会调用其中每个Selector对象的extract方法,并把所有结果收集到一个列表返回给用户
    • selector.extract_first:该方法返回其中第 一个Selector对象调用extract方法的结果
    • selector.re:允许用户通过正则选取内容
    • selector.re_first:返回其中的第一个Selector对象调用re方法的结果
    • 在第一次访问 一个Response对象的selector属性时,Response对象内部会以自身为参数自动创建Selector对象,并将该Selector对象缓存,以便下次使用

模拟登陆

  • 其核心就是向服务器发送含有登录单表数据的HTTP请求(通常是POST)
  • Scrapy提供了一个FormRequest类(Request的子类),专门用于构造含有表单数据的请求,FormRequest的构造器方法有一个formdata参数,接收字典形式的表单数据
  • 方法
    • 直接构造FormRequest对象的方式
    • 调用FormRequest的from_response方法。调用时需传入一个Response对象作为第一个参数,该方法会解析Response对象所包含页面中的'<from'>元素,帮助用户创建FormRequest对象,并将隐藏'<input'> 中的信息自动填入表单数据,使用这种方式,我们只需通过formdata参数填写账号和密码即可

识别验证码

  • 浏览器加载完登录页面后,会携带之前访问获取的Cookie信息,继续发送一个HTTP请求加载验证码图片
  • 识别验证码方式
    • OCR识别
      • 识别的验证码比较简单
      • 光学字符识别,用于在图像中提取文本信息
      • 只需提取验证码图片的url
      • 带有验证码登录时,需要额外发送一个HTTP请求来获取验证码图片
    • 网络平台识别(验证码识别平台)
      • 识别比较复杂的验证码
    • 人工识别
      • —在Scrapy下载完验证码图片后,调用 Image.show方法将图片显示出来,然后调用Python内置的input函数,等待用户肉眼识别后输入识别结果

cookies登录

  • 在使用浏览器登录网站后,包含用户身份信息的Cookie会被浏览器保存在本地,如果Scrapy爬虫能直接使用浏览器中的Cookie发送HTTP请求,就可以绕过提交表单登录的步骤。

爬取动态页面

  • 爬取此类动态网 页需要先执行页面中的JavaScript代码渲染页面,再进行爬取
    • Splash渲染引擎
      • 为用户返回经过渲染HTML页面或页面截图
      • 并发渲染多个页面
      • 关闭图片加载,加速渲染
      • 在页面中执行用户自定义的JavaScript代码
      • 执行用户自定义的渲染脚本,功能类似于phantomjs
      • splash.readthedocs.io/en/latest/a…

分布式爬虫

  • 多爬虫问题
    • 数据共享
    • 在空间上不同的多态机器,可以成为分布式
  • 需要:
    • 共享队列
    • 去重
  • Redis
    • 内存数据库
    • 同时可以落地保存到硬盘
    • 可以去重
    • 可以理解成一共dict,set,list的集合体
    • 可以对保存的内容进行生命周期控制
  • 内容保存数据库
    • MongoDB
    • mysql等传统关系数据库

自然语言处理

  • 语言处理
    • 搜索文本:显示一个指定单词的每一次出现,连同一些上下文一起显示(concordance)
    • 计数词汇
      • 使用len获取长度
    • 将文本做链词表(列表)
    • 索引列表,切片
    • 频率分布,文本中每一个词项的频率
    • 细粒度选择词(通过信息量选择)
    • 词语搭配和双连词
    • 计数其他东西
      • 查看文本中词长的分布
    • 可以对每个元素进行操作
  • 文本语料和词汇资源
    • 最简单的一种是一些孤立的没有什么特别的组织的文本集合;一些语料库按如文体(布朗语料库)等分类组织结构;一些分类会重叠,如主题类别(路透社语料库);另外一些语料库可以表示随时间变化语言用法的改变(就职演说语 料库)
    • 可以载入自己的语料库