1. 程式人生 > 其它 >Python-爬取新浪每日熱門資料

Python-爬取新浪每日熱門資料

1. 初實現

最初是計劃爬取頁面後,使用xpath進行資料解析,並輸出至檔案

程式碼如下:

import requests
from lxml import etree

# url = "https://news.sina.com.cn/hotnews/index_weekly.shtml"
url = "https://news.sina.com.cn/hotnews/"
dic = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"}
response = requests.get(url, headers=dic)
response.encoding = response.apparent_encoding

# 對td進行處理
html = etree.HTML(response.text)

# xpath路徑
target_xpath = '/html/body/div[1]/div[5]/div[2]/table'
div = html.xpath(target_xpath)[0]

# 當前元素中的所有td列表 去除第一個多餘項
td_list = div.xpath('//td')[1:]
item_list = []
# 遍歷td元素列表
for td in td_list:
    title = td.xpath('./a[1]/text()')
    # 若存在子元素,則獲取title
    if len(title) > 0:
        # print(title)
        item_list.append(title)
    else:
        # 若不存在 直接獲取文字值
        item = td.xpath('./text()')
        # 若無文字資料 賦空值
        if len(item) == 0:
            item = ['']
        item_list.append(item)

print(item_list)

# 遍歷item_list
# 將item_list中的分離的內容合併到字典列表中
# 每四個(序號、標題、媒體、時間)一組
news_list = []  # 字典列表
i = 0
while i < len(item_list):
    try:
        num = item_list[i]
        title = item_list[i + 1]
        media = item_list[i + 2]
        time = item_list[i + 3]
        i += 4  # 每四個一組
        news_dic = {"num": num[0], "title": title[0], "media": media[0], "time": time[0]}  # 加入字典
        news_list.append(news_dic)  # 將字典加入列表
    except:
        print("迴圈結束")
        break

# 結果寫入檔案result.txt
for news in news_list:
    # 根據需要切換引數mode a-追加內容 w-寫入內容(覆蓋)
    with open("result.txt", mode='a', encoding="utf-8") as fs:
        fs.write(str(news) + "\n")

2. 出現的問題

  1. 只能當天的資料可以在網頁中顯示,對其他時間的資料爬取存在困難
  2. xpath解析table元素存在問題,直接使用"//td"後處理資料複雜

3. 解決辦法

轉變思路,在使用除錯工具找到獲取資料的連結

https://top.news.sina.com.cn/ws/GetTopDataList.php?top_type=day&top_cat=www_www_all_suda_suda&top_time=20220327&top_show_num=10&top_order=DESC
對此連結進行分析,可以知道其引數的作用:
如top_time為日期,top_show_num為請求數量,top_order為排序方式,top_type為日期範圍
但是獲取到的是js程式碼,並不是我期望的json正確格式

這個var data = 就很煩,使用strip()方法去除掉,並且使用split()方法將最後的分號也去掉

text = response.text.strip('var data=').split(";")[0]

這樣就獲得了完美的json資料,並且通過幾個引數就可以想要的對應時間、日期範圍和數量的資料

4. 完整程式碼

import requests
import json


# json資料輸出為json_data.json檔案
def output_to_file(data, mode='w'):
    # 寫入檔案
    with open("json_data.json", mode=mode) as fw:
        fw.write(json.dumps(data))


top_show_num = 10  # 爬取資料數
top_time = "20220327"  # 時間
top_type = "day"  # 日期型別 day week month
url = f"https://top.news.sina.com.cn/ws/GetTopDataList.php?" \
      f"top_type={top_type}&top_cat=www_www_all_suda_suda&top_time={top_time}" \
      f"&top_show_num={top_show_num}&top_order=DESC"
dic = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"}
response = requests.get(url, headers=dic)
response.encoding = response.apparent_encoding
# print(response.text)
# 擷取多餘元素
text = response.text.strip('var data=').split(";")[0]
print(text)
# json格式化 並獲取data資料
json_data = json.loads(text)["data"]
print(json_data)
index = 0  # 序號
for item in json_data:
    print(index, item['id'], item['title'], item['media'], item['url'], item['time'])
    index += 1
# 所有json輸出至json_data.json
output_to_file(json_data)

可以看到json資料的框架:

根據需要,對json_data提取相應資料就可以啦!

5. 參考連結

https://blog.csdn.net/hanchaobiao/article/details/73150405
https://www.runoob.com/python/att-string-strip.html
https://www.runoob.com/python/att-string-split.html
https://cloud.tencent.com/developer/article/1651280