当前位置:   article > 正文

合工大Python爬虫实验——按关键词爬取新闻网站_根据关键词爬取相关内容

根据关键词爬取相关内容

时隔一年,笔者又拿着实验报告来写篇博客。

实验原理

爬虫实验使用了Python中的requestsbeautifulsoupjsonpandas库,requests用于发送HTTP请求,beautifulsoup用于处理并解析响应的HTML文档,json用于解析json数据,pandas用于数据储存。

1HTTP请求构造

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。

HTTP/1.1协议中共定义了八种方法来以不同方式操作指定的资源:

 GET HEAD POST PUT  DELETE TRACE OPTIONS CONNECT

爬虫大多用的就是GET或者POST

2、响应数据处理

对于请求的响应,一般情况下,有html json 两种格式。

HTML数据的解析原理:HTML以尖括号为标记,内部元素分为块元素与行内元素。利用beautifulsoup可以选择目标元素内的文本,爬取并存储即可完成数据解析。

Json数据解析:JSON类似于XML,是一种数据交换格式。JSON JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包。解析后直接分析键值对即可提取目标信息。

实验设计

    从实验原理出发,模拟整个请求响应流程,防止爬虫被网站阻拦。系统流程与结构如下:

爬虫程序流程如下图:

    系统架构如下图:

关键问题及其解决方法

        爬取信息失败,未能获得正常响应

根据分析,修改header以及参数后发现,原因在于header中没有加入Referer这一键值对,导致网站将程序将程序的请求判定为爬虫。

    在一些网站信息的获取过程中,只有在指定的站点发起请求,服务器才会允许返回数据(这样可以防止资源被盗用在其他网站使用)。因此加入Rerferer使得问题解决。

    解决方法:在相关网站打开开发者工具,观察目标数据包的头部,如下:

根据实际情况合理构造头部即可获得正常响应。

        获得正常响应,但获得的数据并不符合关键词

针对这一问题,同样从url,headers以及参数方向考虑,由于urlheaders并不设计到关键词的值,因此考虑参数的值与格式。

    解决方法:

打开工具查看实际参数

构造相同参数进行测试

结果返回失败,于是考虑格式,发现南方新闻网参数的接收格式为application/x-www-form-urlencoded; charset=UTF-8,直接接收表单,不需要将参数json处理再传输,于是直接发送参数,然后即得到正确结果。

设计结果

参数设置:可根据实际需要,设置关键词

爬取结果展示:

南方新闻网:

新浪新闻:

爬虫源码如下:

南方新闻网爬虫源码:

  1. import requests
  2. from bs4 import BeautifulSoup
  3. import pandas as pd
  4. import os
  5. def fetchUrl(url, kw, page):
  6. # 请求头
  7. headers={
  8. "accept":"*/*",
  9. "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
  10. "origin":"https://search.southcn.com",
  11. "referer": "https://search.southcn.com/?keyword=chatgpt&s=smart&page={}".format(page),
  12. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.58",
  13. }
  14. # 请求参数
  15. payloads = {
  16. "project_id":5,
  17. "service_area":1,
  18. "sort":"smart",
  19. "position": "",
  20. "keywords": kw,
  21. "page_size":10,
  22. "page": page,
  23. "type": "normal",
  24. }
  25. # 发起 post 请求
  26. r = requests.post(url, headers=headers, data=payloads)
  27. return r.json()
  28. def parseJson(jsonObj):
  29. #解析数据
  30. records = jsonObj["data"]["news"]["list"]
  31. for item in records:
  32. # 解析了"文章id", "标题", "副标题", "发表时间", "编辑", "版面", "摘要", "链接"
  33. pid = item["id"]
  34. editor = item["editor"]
  35. content = item["digest"]
  36. displayTime = item["pub_time_detail"]
  37. subtitle = item["sub_title"]
  38. title = BeautifulSoup(item["title"], "html.parser").text
  39. url = item["url"]
  40. yield [[pid, title, subtitle, displayTime, editor, content, url]]
  41. def saveFile(path, filename, data):
  42. # 如果路径不存在,就创建路径
  43. if not os.path.exists(path):
  44. os.makedirs(path)
  45. # 保存数据
  46. dataframe = pd.DataFrame(data)
  47. dataframe.to_csv(path + filename + ".csv", encoding='utf_8_sig', mode='a', index=False, sep=',', header=False )
  48. if __name__ == "__main__":
  49. # 起始页,终止页,关键词设置
  50. start = 1
  51. end = 5
  52. keyword = "chatgpt"
  53. # 保存表头
  54. headline = [["文章id", "标题", "副标题", "发表时间", "编辑", "摘要", "链接"]]
  55. saveFile("./data/", "southcn", headline)
  56. #爬取数据
  57. for page in range(start, end + 1):
  58. url = "https://search.southcn.com/api/search/all"
  59. html = fetchUrl(url, keyword, page)
  60. for data in parseJson(html):
  61. saveFile("./data/", "southcn", data)
  62. print("第{}页爬取完成".format(page))

新浪新闻网爬虫:

  1. import requests
  2. from bs4 import BeautifulSoup
  3. import pandas as pd
  4. import os
  5. from lxml import etree
  6. def fetchUrl(url, kw,page):
  7. # 请求头
  8. headers = {
  9. "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
  10. "content-type": "application/x-www-form-urlencoded",
  11. "origin": "https://search.sina.com.cn",
  12. "referer": "https://search.sina.com.cn/news",
  13. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.58",
  14. }
  15. # 请求参数
  16. payloads = {
  17. "q":kw,
  18. "c":"news",
  19. "range":"all",
  20. "size":10,
  21. "page":page
  22. }
  23. # 发起 post 请求
  24. r = requests.post(url, headers=headers, data=payloads)
  25. return r
  26. def parseHtml(htmlObj):
  27. html_selector = BeautifulSoup(htmlObj.text,'lxml')
  28. news = html_selector.find_all("div",attrs = {'class': 'box-result clearfix'})
  29. # 解析数据
  30. for item in news:
  31. # 解析"文章标题", "摘要", “来源与发表时间", "链接"
  32. title = item.find("a").text
  33. content = item.find("p",attrs = {"class":"content"}).text
  34. origin = item.find("span",attrs = {"class":"fgray_time"}).text
  35. url = item.find("a")['href']
  36. yield [[title, content,origin, url]]
  37. def saveFile(path, filename, data):
  38. # 如果路径不存在,就创建路径
  39. if not os.path.exists(path):
  40. os.makedirs(path)
  41. # 保存数据
  42. dataframe = pd.DataFrame(data)
  43. dataframe.to_csv(path + filename + ".csv", encoding='utf_8_sig',
  44. mode='a', index=False, sep=',', header=False)
  45. if __name__ == "__main__":
  46. # 起始页,终止页,关键词设置
  47. start = 1
  48. end = 3
  49. keyword = "chatgpt"
  50. # 保存表头
  51. headline = [["文章标题", "摘要", "来源与发表时间", "链接"]]
  52. saveFile("./data/", "sinanews", headline)
  53. # 爬取数据
  54. for page in range(start, end + 1):
  55. url = "https://search.sina.com.cn/news"
  56. html = fetchUrl(url, keyword, page)
  57. for data in parseHtml(html):
  58. saveFile("./data/", "sinanews", data)
  59. print("第{}页爬取完成".format(page))

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/616420
推荐阅读
相关标签
  

闽ICP备14008679号