zoukankan      html  css  js  c++  java
  • python爬虫-爬坑之路

    背景简介

    爬取外国的某两个网站的数据,网站都没有被墙,爬取三种数据。

    • A: 爬取页面并存储到数据库
    • B: 爬取页面内的表格内数据并存储到数据库
    • C: 爬取页面,分析页面并将页面的所有数据分类存入数据库,且页面内存在下级页面,也需要进行同样的操作

    python包选取以及使用

    连接链接

    在windows电脑上编写调试代码,在linux服务器上运行代码

    由于包的差异原因,根据系统选择了两种不同的连接方式(非最佳选择)

    windows - urllib3

    linux - pycurl、urllib(pycurl连接GET类型的链接时,需要使用urllib.parse对该链接的参数数据进行处理)

    注:以下部分处理方法是经对该网站的所有测试,包括连接速度、连接时长、错误类型等进行尽量全面的测试之后采取的方法,不适用所有网站,需要酌情使用

    urllib3

    # method: 连接链接的方式-GET/POST
    # url: 链接地址
    # data: 连接链接时需要传输的参数数据
    
    def getHtmlByLib(method, url, data):
        try:
            http = urllib3.PoolManager(timeout=1000) # 经测试得出:外国网站的连接速度由于时差原因会有不同的延迟,设置超时timeout为1000秒
            r = http.request(method, url, fields=data)
            html = r.data.decode("utf-8", "ignore") # 将网站页面源代码转换为utf-8时会报转换错误,衡量后使用 ignore 模式,会忽略转换错误的代码
            return html
        except:
            return getHtmlByLib(method, url, data) # 在连接失败或其他错误发生时,重新连接该地址
    

    pycurl

    class htmlContents:
        def __init__(self):
            self.contents = ''
        def callback(self, curl):
            self.contents = self.contents + curl.decode("utf-8", "ignore")
    
    
    def getHtmlByCurl(method, url, data):
        t = htmlContents()
        curl = pycurl.Curl()
        # 设置连接链接时的传输参数
        if(len(data) > 0):
            curl.setopt(pycurl.POSTFIELDS, urllib.parse.urlencode(data))
        # 设置头部
        headers = ["Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
        "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"]
        curl.setopt(pycurl.HTTPHEADER, headers)
        # 连接时长与curl的连接时长
        curl.setopt(pycurl.CONNECTTIMEOUT, 1000)
        curl.setopt(pycurl.TIMEOUT, 900)
        # 传输速度 传输速度小于1字节/秒的状态持续90秒,该连接就会终止
        curl.setopt(pycurl.LOW_SPEED_TIME, 90)
        curl.setopt(pycurl.LOW_SPEED_LIMIT, 1)
        # 连接成功以后的处理方法
        curl.setopt(pycurl.WRITEFUNCTION, t.callback)
        curl.setopt(pycurl.ENCODING, 'gzip, deflate')
        curl.setopt(pycurl.URL, url)
        # 设置连接以及下载速度的进度条展示
        curl.setopt(pycurl.NOPROGRESS, 0)
        # 把cookie保存在该文件中
        # curl.setopt(pycurl.COOKIEFILE, "cookie_file_name")
        # curl.setopt(pycurl.COOKIEJAR, "cookie_file_name")
        # POST方式
        if(method == "POST"):
            curl.setopt(pycurl.POST, 1)
        try:
            curl.perform()
        except pycurl.error as e:
            curl.close()
            return getHtmlByCurl(method, url, data)
        # 获取HTTP_CODE
        httpCode = curl.getinfo(curl.HTTP_CODE)
        curl.close()
        if(httpCode != 200):
            return getHtmlByCurl(method, url, data)
        # 页面内容
        return t.contents
    

    处理页面

    bs4/json

    bs4使用教程

    爬取页面(A)

    评价 : 比较简单,可以作为入门的爬虫,不是单纯的抓取页面,需要获取一些页面内的简单的数据。

    使用bs4.BeautifulSoup进行页面数据的格式化

    soup = BeautifulSoup(html, features="html.parser")

    大略步骤如下

    1. 获取所有国家options = soup.find("select", id="country6").find_all("option")
    2. 根据国家ID连接链接获取报告列表,解析列表内数据,获取该国家每一年的每份报告的是否存在以及报告链接
    3. 连接报告链接获取页面源代码,并根据需求删除代码内节点树的某些节点
    4. 存入数据库

    知识点

    1. BeautifulSoupfind_all()以及find()方法的使用

      • find_all() - 获取某个节点下的所有符合条件的节点,不单止子节点,而是所有子孙节点内符合条件的节点
      • find() - 获取左右子孙节点内第一个符合条件的节点
    2. BeautifulSoup的删除节点事件、删除节点

      • 删除节点事件

         divs = soup.find_all("div")
         for div in divs:
         	if(div.has_attr('onmouseover')):
         		del div["onmouseover"]
        
      • 删除节点 - div.decompose()

    3. BeautifulSoup输出页面源代码 - print(soup.prettify())

    获取页面内的数据并处理(B)

    爬取页面内的表格内数据并存储到数据库

    评价:需求A的进阶型,主要针对选择页面内下拉列表的选项之后的请求的处理,主要处理json数据,需要对页面内JS方法的理解、在浏览器内使用开发者工具时的有效链接筛选

    大略步骤如下:

    1. 获取第一个页面,解析页面源代码,了解后续操作所产生的JS事件以及影响,并通过浏览器开发者工具筛选出有效链接
    2. 连接第一步筛选出的有效链接,获取该链接传输来的json数据
    3. 获取最终目标链接所需要的传输参数。从第二步的json数据中获取;从第一部的初始页面获取;
    4. 连接目标链接,传输参数数据,并处理最终数据,存入数据库

    知识点

    1. 该网站对连接次数做出了限制,会返回409状态码,并告知USAGE LIMIT: Hourly usage limit of 100 actions reached. You may resume use of this service at XXXX-XX-XXT03:43:10Z

      代码调整:1. 连接链接时设置休眠时间,time.sleep(10),可以减少409状态码的出现次数;2. 出现409状态码时,休眠10分钟time.sleep(60*10)

    2. 字符串转换为json

      import json
      jsonData = json.loads(data)
      

    处理页面内所有数据并存储入数据库(C)

    评价:由于该页面内容的多变性,数据处理方式需要更兼容,故认为为B需求的进阶型,基于B需求之后可以更容易筛选出有效链接,主要处理table内数据。

    大略步骤如下:

    1. 获取第一个页面,获取页面内容并通过浏览器开发者工具筛选出有效链接
    2. 连接第一步筛选出的有效链接,获取页面内的table内容以及需要的数据,包括URL
    3. 连接table内的URL并获取页面源代码,使用BeautifulSoup对页面内容进行处理,获取需要的数据

    知识点

    1. table的tr/td处理,子节点获取

      tableChoisir = soup.find("table", attrs={"class": "TableChoisir"})
      trsList = []
      for trChild in tableChoisir.children:
          # 子节点除了html节点以外,如换行、空白字符等也被视为子节点
          trChild = formatString(str(trChild))
          if len(trChild.strip(" ")) > 0:
              trSoup = bsHtml(trChild)
              trsList.append(trSoup)
      
    2. 获取节点内容

      title = trSoup.find("td", attrs={"class": "topbigtabletitle27"}).get_text()

    总结叙述

    1. 使用bs4.BeautifulSoup可以很轻松的获取页面节点的所有内容
    2. pycurl的连接速度优于urllib3,同时也需要设置很多参数,pycurl可视为linux下的curl命令的封装,pycurl的参数设置可参考libcurl
  • 相关阅读:
    DRF频率、分页、解析器、渲染器
    DRF的版本、认证、权限
    Django Rest Framework 视图和路由
    restfull规范
    DRF序列化
    类的super
    AngularJs自定义指令详解(1)
    AngularJs自定义指令详解(5)
    angular 自定义指令详解 Directive
    require js define 函数
  • 原文地址:https://www.cnblogs.com/fengzzi/p/11008655.html
Copyright © 2011-2022 走看看