Python-爬取新浪每日熱門資料
阿新 • • 發佈:2022-03-27
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. 出現的問題
- 只能當天的資料可以在網頁中顯示,對其他時間的資料爬取存在困難
- 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