Daibingh Less is more, slow is fast.

爬虫小结

2019-11-26
hdb

分析: Google Chrome Devtools 使用

  • F12 查看元素
  • 定位元素
  • network 按请求类型查看
  • 移动版切换
  • sources 查看源文件
  • 生成 url 请求参数
      # 使用 urlencode 
      from urllib.parse import urlencode
      params = {'a': 1, 'b': 2}
      params_str = urlencode(params)
      print(params_str)  # 'a=1&b=2'
        
      # 或直接作为参数传递给 requests.get()
    
  • 文本编码
      from urllib.parse import quote
      str_encode = quote('真的厉害!')  # '%E7%9C%9F%E7%9A%84%E5%8E%89%E5%AE%B3%EF%BC%81'
    

请求

  • get 请求
      import requests
      headers = {'x': 'xx'}
      params = {'a': 1, 'b': 2}
      url = 'xxx.xxx.xx'
      rs = requests.get(url, params=params, headers=headers)
    
  • post 请求
      import requests
      headers = {'x': 'xx'}
      data = {'a': 1, 'b': 2}
      url = 'xxx.xxx.xx'
      rs = requests.get(url, data=data, headers=headers)
    

解析与定位

  • html 预处理
      import requests
      url = 'xxx'
      rs = requests.get(url)
      html = rs.content.decode('utf-8').replace('\r\n', '')  # 去除换行符
        
      # clean xml. https://stackoverflow.com/questions/3310614/remove-whitespaces-in-xml-string
      from lxml import etree
      def clean_xml(xml):
          parser = etree.XMLParser(remove_blank_text=True)
          elem = etree.XML(xml, parser=parser)
          return etree.tostring(elem)
    
  • 定位元素
    • bs4
        from bs4 import BeautifulSoup as bs
        soup = bs(html, 'lxml')  # <class 'bs4.BeautifulSoup'>
              
        # select 定位
        results = soup.select('#translateResult')  # select 支持 css,选择器语法,返回所有满足条件的 一个 list
        result = soup.select_one('#translateResult')   # 返回单个结果
        type(results[0])  # <class 'bs4.element.Tag'> 每个节点都是 Tag 类型
              
        # find, findAll 定位,支持正则表达式
        result = soup.find('tag_name', {'property_name1': 'value1', 'property_name2': re.compile(r'xxxx'), ...})  # find 只返回第一个匹配结果
        results = soup.findAll('tag_name', {'property_name1': 'value1', 'property_name2': re.compile(r'xxxx'), ...})  # 返回 list, 所有匹配
        soup.find_all(href=re.compile("elsie"))  # 通过属性找
        soup.find_all(href=re.compile("elsie"), id='link1')  #  通过多个属性找
        data_soup.find_all(attrs={"data-foo": "value"})
        soup.find_all("a", class_="sister")
        soup.find_all("a", string="Elsie")  # string 参数
        soup.html.find_all("title", recursive=False)  # 调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False
              
        # Tag 对象属性与方法
        tag.text.strip()
        tag.get('key')
        tag.has_attr('key')
        tag.find()
        tag.findAll()
        tag.select()
              
        # 导航
        tag.parent  # 返回直接父级 Tag
        tag.children  # <class 'list_iterator'>
        tag.next_sibling  # 下一个兄弟标签
        tag.previous_sibling  # 上一个兄弟标签
      
    • re
        re.findall(pattern, str)  # 返回匹配的字符串列表,pattern中使用( )可以只返回( )中的部分
        re.search(pattern, str)  # 返回第一个匹配的正则表达式对象,可以使用( ) + *.group(n)
        re.sub(pattern, repl, str)  # 替换,可以使用( ) + \1 反向引用
        pattern = re.compile(r'<ul id="translateResult">\W*?<li>(.*?)</li>\W*?</ul>', re.S)  #  re.S 作为 flag,让 . 号也匹配换行符
        matches = re.findall(pattern, html)
      

存储

待补充 …


Similar Posts

Comments