近年来,百度搜索时常因为其搜索时出现的各种广告而被各大网友吐槽,更是爆出了“莆田医院魏则西”这样的令人叹息的事情。如下为百度搜索“模拟器”时,出现了整整4条广告。

    1.jpg

    但是作为一个商业的搜索引擎,出现广告确实是可能的,不光是百度,连谷歌也会出现各种广告。如下图,为检索“模拟器”时谷歌页面出现的广告。

    q.png

    当然,在百度面前,谷歌的搜索结果显得简洁很多,尤其是广告方面也相对较少,但是使用谷歌其实并不方便,需要各种途径才能使用谷歌,这对广大普通网友的时候造成了较大的困扰。所以,在这种情况下,对百度检索的结果进行一个广告的过滤显得尤为重要。正好计网大作业要求做一个爬虫的大作业,所以我就以此为基础,来开发一个爬虫程序。
    我的目的在于对百度搜索的结果进行一个过滤,将其中的广告项删除,并以简洁的网页形式展示出来。

    2.png

    首先要用的是Python(Python 3.7.3),利用Python的爬虫技术,可以将百度的搜索结果爬取下来,并进行一系列的筛选。因为输入关键词的部分在前端实现,所以我还需要一个能够连接前后端的框架,此处采用了Django(Django 3.1.0)的框架进行前后端的交互。 在获取到了相应的结果之后,还需要展示在页面上,所以此处依旧需要使用Web前端的三板斧 HTML + CSS + JavaScript,同时本来我想采用React框架进行布局,但是后来发现这样在Django框架下实现前后端分离并不方便,所以还是使用较少。
    对源代码进一步分析可以看出,检索项之间的CSS样式是有区别的,

    3.png

    例如这是一条广告的div,可以看到这个div采用的样式是class= “tJZBfX JLycWg mFCSNH c-container new-pmd”,而对正常的检索项,div使用的样式则是class=”result c-container new-pmd”,可以看到,在广告项里的class使用了更多的样式,这就使得我在对爬取到的内容可以进行一些筛选了。

    4.png

    经过了大量的研究,我发现所有的检索结果只要是非推广内容的,均是class=”result c-container new-pmd”,所以只需要对这一项使用正则表达式判断,即可将所有商业推广的内容去除。除此之外,我还发现了一个最简单的方法,那就是对百度检索出来的id进行判断,因为所有非商业推广的内容是会赋值id = “?”,这也就使得我可以用更简单的方法,只需要div中含有id项的即可进行筛选。

    部分代码如下:

    1. def get_url(keyword, pages):
    2. params = {
    3. 'wd': str(keyword)
    4. }
    5. # https://www.baidu.com/s?wd=xpath&pn=21 这是查到第三页的例子
    6. url = "https://www.baidu.com/s"
    7. url = format_url(url, params)
    8. if int(pages) == 1:
    9. page = 1
    10. else:
    11. page = (int(pages) - 1) * 10
    12. url = url + '&pn=' + str(page)
    13. print(url)
    14. return url
    15. def get_page(url):
    16. try:
    17. headers = {
    18. 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
    19. 'accept-language': 'zh-CN,zh;q=0.9',
    20. 'cache-control': 'max-age=0',
    21. 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
    22. }
    23. response = requests.get(url=url,headers=headers)
    24. # 更改编码方式,否则会出现乱码的情况
    25. response.encoding = "utf-8"
    26. if response.status_code == 200:
    27. return response.text
    28. return None
    29. except RequestException:
    30. return None
    31. def parse_page(url, page):
    32. i = page
    33. title = ""
    34. sub_url = ""
    35. abstract = ""
    36. flag = 11
    37. if i == 1:
    38. flag = 10
    39. html = get_page(url)
    40. content = etree.HTML(html)
    41. for j in range(1,flag):
    42. data = {}
    43. res_title = content.xpath('//*[@id="%d"]/h3/a' % ((i - 1) * 10 + j))
    44. if res_title:
    45. title = res_title[0].xpath('string(.)').replace('\n','').strip()
    46. print("title是")
    47. print(title)
    48. sub_url = content.xpath('//*[@id="%d"]/h3/a/@href' % ((i - 1) * 10 + j))
    49. if sub_url:
    50. sub_url = sub_url[0]
    51. print("sub_url是")
    52. print(sub_url)
    53. res_abstract = content.xpath('//*[@id="%d"]/div[@class="c-abstract"]'%((i-1)*10+j))
    54. if res_abstract:
    55. abstract = res_abstract[0].xpath('string(.)')
    56. else:
    57. res_abstract = content.xpath('//*[@id="%d"]/div/div[2]/div[@class="c-abstract"]'%((i-1)*10+j))
    58. if res_abstract:
    59. abstract = res_abstract[0].xpath('string(.)')
    60. data['title'] = title
    61. data['sub_url'] = sub_url
    62. data['abstract'] = abstract
    63. if sub_url != []:
    64. yield data

    在这样的处理之后,就基本得到了我所需的检索项标题,检索项链接,检索项摘要。在这样的情况下,再使用爬虫进行内容的爬取,就可以得到相应的结果。

    5.png

    在这样进行爬取之后,获得的结果就是没有商业推广结果的信息了,爬取结果均用json文件的形式保存下来方便之后使用。软件的编写应该对用户友好,所以此处我要新建一个用于前端输入检索关键字的页面,于是我需要使用到Django进行前后端的交互。最终得到了如下的结果:

    6.png
    7.png

    对比没有过滤的搜索结果

    8.png