zoukankan      html  css  js  c++  java
  • Python爬虫_百度贴吧(title、url、image_url)

    本爬虫以百度贴吧为例,爬取某个贴吧的【所有发言】以及对应发言详情中的【图片链接】

    涉及:

    1. request 发送请求获取响应
    2. html 取消注释
    3. 通过xpath提取数据
    4. 数据保存

    思路:

    • 由于各贴吧发言的数量不一,因此通过观察url规律统一构造url列表进行遍历爬取,不具有可推广性,因此通过先找到【下一页】url,看某一页是否存在下一页url决定爬虫的停止与否
    • 对初始url 进行while True,直到没有下一页url为止
      • 发送请求获取响应
      • 提取数据(标题列表、url列表、下一页url)
        • 遍历url列表
          • 对初始url 进行while True,直到没有下一页url为止
            • 发送请求获取响应
            • 提取数据(image_url_list、下一页url
          •  保存数据

    代码:

     1 import requests
     2 from lxml import etree
     3 import json
     4 
     5 
     6 class TieBaSpider:
     7     def __init__(self):
     8         self.proxies = {"http": "http://122.243.12.135:9000"}  # 免费ip代理
     9         self.start_url = "https://tieba.baidu.com/f?kw={}&ie=utf-8&pn=0"
    10         self.headers = {
    11             "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.k36 (KHTML, like Gecko) "
    12                           "Chrome/86.0.4240.11"}
    13 
    14     # 发送请求获取响应
    15     def parse_url(self, url):
    16         res = requests.get(url, headers=self.headers, proxies=self.proxies)
    17         html_str = res.content.decode().replace(r"<!--", "''").replace(r"-->", "''")  # 去除网页注释
    18 
    19         return html_str
    20 
    21     # 提取外层url内容列表
    22     @staticmethod
    23     def get_outer_content(html_str):
    24         html = etree.HTML(html_str)
    25         title_list = html.xpath("//a[@class='j_th_tit ']/text()")
    26         url_list = html.xpath("//a[@class='j_th_tit ']/@href")
    27         if len(html.xpath("//a[text()='下一页']/@href")) > 0:
    28             next_url_outer = html.xpath("//a[text()='下一页'/@href")[0]
    29         else:
    30             next_url_outer = None
    31 
    32         return title_list, url_list, next_url_outer
    33 
    34     # 提取内层url内容列表
    35     @staticmethod
    36     def get_inner_content(html_str):
    37         html = etree.HTML(html_str)
    38         image_list = html.xpath("//img[@class='BDE_Image']/@src")
    39 
    40         if len(html.xpath("//a[text()='下一页']/@href")) > 0:
    41             next_url_inner = 'https://tieba.baidu.com' + html.xpath("//a[text()='下一页']/@href")[0]
    42         else:
    43             next_url_inner = None
    44 
    45         return image_list, next_url_inner
    46 
    47     # 保存数据
    48     @staticmethod
    49     def save(comment):
    50         with open("tb.txt", "a", encoding="utf8") as f:
    51             f.write(json.dumps(comment, ensure_ascii=False, indent=2)+"
    ")
    52 
    53     # 主函数
    54     def run(self):
    55         # 初始化保存数据的字典
    56         comment = {}
    57         # 构造 url
    58         url = self.start_url.format("费德勒")
    59         # 初始化外层循环条件
    60         next_url_outer = url
    61         while next_url_outer is not None:  # 循环外层的每一页
    62             html_str = self.parse_url(next_url_outer)  # 发送请求,获取响应
    63             title_list, url_list, next_url_outer = self.get_outer_content(html_str)  # 提取数据(标题,下一页url)
    64             i = 0
    65             for url_inner in url_list:  # 循环外层的某一页
    66                 image_list_all = []  # 初始化存放img_url的列表
    67                 url_inner = 'https://tieba.baidu.com' + url_inner  # 构建url
    68                 image_list, next_url_inner = self.get_inner_content(self.parse_url(url_inner))  # 获取数据
    69                 image_list_all.extend(image_list)
    70 
    71                 while next_url_inner is not None:  # 循环某一页上的某一个url
    72                     html_str = self.parse_url(next_url_inner)
    73                     image_list, next_url_inner = self.get_inner_content(html_str)
    74                     image_list_all.extend(image_list)
    75 
    76                 comment["title"] = title_list[i]
    77                 comment["url"] = url_inner
    78                 comment["img_url"] = image_list_all
    79 
    80                 self.save(comment)
    81                 i += 1
    82                 print("ok")
    83 
    84 
    85 if __name__ == "__main__":
    86     tb = TieBaSpider()
    87     tb.run()

     

  • 相关阅读:
    node
    前端工程师的思考
    前端工程师需要具备的条件
    产品经理必须掌握的名词
    金融人必须掌握的词汇
    央企降两金、降杠杆的 “兵器谱”
    抽屉协议
    清分、清算、结算的关系
    如何有效规避风险
    浅谈在项目管理过程中风险管理
  • 原文地址:https://www.cnblogs.com/waterr/p/13923793.html
Copyright © 2011-2022 走看看