Python轻松爬取百度搜索信息

举报
香菜聊游戏 发表于 2021/10/24 20:52:43 2021/10/24
【摘要】 前段时间一个粉丝加我好友,希望能让我帮忙做一些事情,就是对百度的搜索结果进行采集,同时对格式进行处理,至于具体的用处我也没有太关注,毕竟粉丝也包了一个大红包,希望他能发财吧,今天就大概的把源码的实现过程进行分析,展示下。粉丝之前也找了两个人帮忙开发,最终的结果估计是不了了之,钱花了没有结果,所以找到我,从目前的的粉丝反馈来看对结果还是满意是的,能完成他的需求,也能得到不错的结果。需求一、 在...

前段时间一个粉丝加我好友,希望能让我帮忙做一些事情,就是对百度的搜索结果进行采集,同时对格式进行处理,至于具体的用处我也没有太关注,毕竟粉丝也包了一个大红包,希望他能发财吧,今天就大概的把源码的实现过程进行分析,展示下。

粉丝之前也找了两个人帮忙开发,最终的结果估计是不了了之,钱花了没有结果,所以找到我,从目前的的粉丝反馈来看对结果还是满意是的,能完成他的需求,也能得到不错的结果。

需求

一、 在搜索引擎中搜索一个长尾关键词,采集排在前三名的文章标题和正文内容,然后把这三篇文章保存到同一个txt格式文本里面。此txt文本名为当前搜索词。文章内容段落分明。或者保持它原始段落。目的是可以有良好的阅读体验。

二、 只采集有正文内容的详情页,如果排名前三的是网站首页 或者是列表页 、或者是 百度图片、百度地图、阿拉丁等内容 ,可直接可以跳过,接着往下判断,直到采集到三篇有实质性文章内容的页面。如:排名前三的是知乎 百度知道等网站,只采集一楼用户回答的内容即可。

三、 可以导入多个(几千个几万个)搜索的长尾关键词,以txt方式导入、或 表格方式导入。可以选择采集下来生成文章的保存位置。

截图详细说明:以搜索” 深圳化妆培训学校哪家比较好”为例。

问题分析

因为每个网站的结构不一样,所以想要写出通用的代码是不行的,所以需要对网站定制,每个特殊的网站可以写专用的解析器,这样才能完美的完成粉丝的需求。

首先用粉丝给的几个关键字,做了一波搜索,然后分析了一波,成功的引出了粉丝新的需求,对 知乎 百度知道 百家号这样的网站每个回答需要取出第一条答案

然后在讨论一波后锁定需要将内置的网站的答案前置,比如搜索之后又10条,即使内置网站的答案不在最前面,也要优先内置网站的数据

因为需要内置一些网站,为了更好的解析,所以需要定制解析器,好在粉丝会一些html知识,所以我提供了内置的教程,方便后续粉丝增加网站

源码展示

环境:

python3.5 requests 还有 BeautifulSoup

源码

import requests
from bs4 import BeautifulSoup
​
headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, compress',
    'Accept-Language': 'en-us;q=0.5,en;q=0.3',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'
}  # 定义头文件,伪装成浏览器
global index
keyword = ''
maxCount = 3
​
​
# 百家号
def readBaijiahao():
    return True,'div', {"class": ["article-content", "index-module_articleWrap_2Zphx"]}
​
​
# 百度知道
def readBaiduAsk():
    return False,'div', {"accuse": ["aContent"]}
​
​
# 知乎
def readZhihu():
    return True,'div', {
        "class": ["RichContent-inner", "RichText ztext Post-RichText", "RichText ztext Post-RichText css-hnrfcf"]}
​
​
readerMap = {
    "baijiahao.baidu.com": readBaijiahao(),
    "zhihu.com": readZhihu(),
    "zhidao.baidu.com": readBaiduAsk()
    # 插入到这里
}
​
​
class Spide:
    def __init__(self):
        self.index = 0
        self.keyword = ''
        self.defineSite = []
        self.commoneSite = []
​
    def readFile(self):
        with open("query.txt", "r", encoding='utf-8') as f:
            data = f.readlines()
            return data
​
    def get_content(self, url):
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()  # 如果返回的状态码不是200, 则抛出异常;
            response.encoding = 'gb2312'  # 判断网页的编码格式, 便于respons.text知道如何解码;
        except Exception as e:
            print("爬取错误")
        else:
            print(response.url)
            print("爬取成功!")
            content = response.text
            return content
​
    def write2File(self, article):
        fileName = "doc/" + self.keyword + '.txt'
        with open(fileName, 'a+', encoding='utf-8') as f:
            if self.index != 0:
                f.write('\n' + self.keyword + '\n'+ '\n')
            for line in article:
                f.write(line)
                f.write( '\n\n')
            f.writelines('\n')
​
    def readContent(self, div,readP):
        if div is None:
            return False
        article = []
        hasText = False
        if readP:
            pList = div.find_all('p')
            for x in pList:
                if len(x.text.lstrip()) != 0:
                    hasText = True
                    article.append(x.text.lstrip().replace('\n', '').replace(' ', ''))
        else:
            con = div.text.lstrip().replace('\n', '').replace(' ', '')
            hasText = len(con)>0
            article.append(con)
        if hasText:
            self.write2File(article)
        return hasText
​
        # if hasText:
        #     self.write2File(article)
        # return hasText
​
    def readCache(self, cacheContent):
        soup = BeautifulSoup(cacheContent, 'html.parser')
        try:
            srcSite = soup.find('div', id='bd_snap_note').find('a')['href']
            # if readerMap.has_key()
            isDefineSite = False
            for defineSite in readerMap.keys():
                if srcSite.find(defineSite) != -1:
                    self.defineSite.append({soup: readerMap.get(defineSite)})
                    isDefineSite = True
                    break
            if not isDefineSite:
                self.commoneSite.append(soup)
        except:
            pass
​
    def getItem2(self, content):
        # # 实例化soup对象, 便于处理;
        soup = BeautifulSoup(content, 'html.parser')
        # 百度快照
        divObj = soup.find_all('a', attrs={'data-click': "{'rsv_snapshot':'1'}"})
​
        for h3 in divObj:
            gwList = h3.parent.parent.find_all('a')
            isGw = False
            for aLink in gwList:
                if aLink['href'] == "http://trust.baidu.com/vstar/official/intro?type=gw":
                    isGw = True
                    break
            if isGw:
                continue
            # h3
            if h3.next_sibling != None and h3.next_sibling.next_sibling != None and h3.next_sibling.next_sibling.text == '翻译此页':
                continue
            href = h3.get('href')
            cacheContent = self.get_content(href)
            self.readCache(cacheContent)
​
        if len(self.defineSite) > 0 and self.index < maxCount:
            for item in self.defineSite:
                soup, readerTuple = item.popitem()
                div = soup.find(readerTuple[1], readerTuple[2])
                if self.readContent(div,readerTuple[0]):
                    self.index = self.index + 1
                if self.index >= maxCount:
                    break
        # 如果想使用通用的解析可以打开下面的代码
        # if len(self.commoneSite) > 0 and self.index < maxCount:
        #     for soup in self.commoneSite:
        #         self.index = self.index + 1
        #         bodyStr = soup.find('body').text.strip().replace('\n', '').replace(' ', '')
        #         self.write2File(bodyStr)
        #         if self.index >= maxCount:
        #             break
​
    def searchKeyword1(self, keyword):
        self.keyword = keyword
        self.index = 0
        self.defineSite.clear()
        self.commoneSite.clear()
        url = 'http://www.baidu.com.cn/s?ie=utf-8&f=8&rsv_bp=1&ch=11&tn=98010089_dg&wd=' + keyword + '&pn=0&rqlang=cn&rsv_dl=tb&rsv_sug3=1&rsv_sug2=0&rsv_btype=t&inputT=769&rsv_sug4=769&rsv_jmp=slow'
        # url = 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&ch=11&tn=98010089_dg&wd=python%20%E7%99%BE%E5%BA%A6%E6%90%9C%E7%B4%A2&oq=python%2520%25E7%2599%25BE%25E5%25BA%25A6&rsv_pq=a624eea1000fb87b&rsv_t=2e3dlaNMWUbo7mECejoQwxZykgFnOYIZq64YSw0RugY%2FO1ONhHN6xF8IC%2B97V8NHxCY&rqlang=cn&rsv_dl=tb&rsv_sug3=1&rsv_sug2=0&rsv_btype=t&inputT=769&rsv_sug4=769&rsv_jmp=slow'
​
        content = self.get_content(url)
        # time.sleep(3)
        if content is not None:
            self.getItem2(content)
​
​
if __name__ == '__main__':
    spide = Spide()
    keywordList = spide.readFile()
    for keyword in keywordList:
        keyword = keyword.strip('\n')  # 去掉列表中每一个元素的换行符
        spide.searchKeyword1(keyword)
​
复制代码

总结:

爬取数据很简单,中间也遇到了一些问题,在和粉丝的沟通中需求在变更,大概的代码就像下面这样


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。