详解爬取搜狐号自媒体的所有文章
背景
現在有很多自媒體平臺,如頭條號、搜狐號、大魚號、百家號等,每個人都可以成為創作者發布自己的作品。如果想把某個作者的文章都下下來,一篇一篇的下載會很麻煩,而用爬蟲則會很簡單,順便還能練練手。這里就以抓取規則比較比較簡單的搜狐號來開到。
?
工具
pycharm、Python3、PC
庫 os、 re、BeautifulSoup、requests、json、urllib.parse
思路
入口URL進入 --> 獲取文章地址 --> 獲取圖片地址 --> 下載文章與圖片
注:主線思路很簡單,但還是會遇到很多小問題
開始
一、網站分析
1、先選定一個要爬取的自媒體賬號,比如隨便選的:
?
2、用fiddler或F12抓包,發現返回的數據包里面不包含連接。這說明連接應該都放在在某個請求里面,而這個請求返回的是json格式。
?
3、在請求列表里找,最終在這個里面看到了貓膩
?
用瀏覽器訪問下試試,好多URL和title,就是這個了!
?
4、在看他的地址結構,pageNumber應該是第幾頁,xpt是每個自媒體賬號的唯一id,pageSize是一頁顯示多少條信息。
?
5、點進一篇文章,發現文章內容在<article>標簽內
?
6、分析完成后,可以正式敲代碼了。
?
二、編碼
1、先對輸入的URL進行拆分,提取xpt
?
2、創建文件夾,存放爬取的資源
?
3、然后用pageNumber、xpt、pageSize拼接路徑,獲取保存URL的頁面;將返回的數據轉為json格式,解析地址;通過pageNumber自增,循環獲取所有頁面的地址。
?
4、將信息保存到本地txt文件
?
5、遍歷獲取地址對應的文章內容和圖片
?
?
?
?
6、效果如下
?
?
?
?
?
優化
由于加了圖片下載,單線程會比較慢,因此可考慮優化成 多線程,效率杠杠滴。
結語
獲取.py源碼和生成的.exe程序:鏈接:https://pan.baidu.com/s/1zGOrI5A60oMapRnQyYoG9g?
提取碼:hkrh?
?
附件:
# -*- coding: utf-8 -*-import sys, os import re import time from bs4 import BeautifulSoup import requests import json import urllib.parsedef get_url(xpt): # 獲取URL集合url_buf = [] # 存放URLdatas = []pagenumber = 0 # 頁數for i in range(20): # 默認20頁pagenumber = pagenumber + 1print(">> 解析第[%d]頁" % pagenumber)url_ori = r"https://mp.sohu.com/apiV2/profile/newsListAjax?xpt=" + xpt + "=&pageNumber=" + str(pagenumber) + r"&pageSize=10&categoryId=&_=1550238383382"try:html = requests.get(url_ori).json()html_json = json.loads(html) # 轉為json格式except Exception as e:print(e)finally:if(str(html_json["data"])=="[]"): # 空數據breakelse:datas.append(html_json["data"]) # 存信息print(datas[pagenumber-1])print("解析完畢\r\n")print(">> 分割地址:")id = 0if (os.path.exists("spider.txt")): # 如果已經存在os.remove("spider.txt") # 刪除該文件for i in datas:for j in i:id = id + 1title = urllib.parse.unquote(j["title"]) # utf8轉中文顯示url = "http://" + j["url"].split("//")[1]print("["+str(id)+"] ", title, " ", url)url_buf.append("["+str(id)+"] "+title+" "+url) # 存入 名稱+地址with open("spider.txt", 'a+', encoding='utf-8') as fp:fp.write("*" * 100 + "\n")fp.write("["+str(id)+"] "+title+" "+url+"\n") # 寫入本地文件fp.close()print(">> 地址信息已保存到本地")return url_bufdef get_content(url_buf): # 獲取地址對應的文章內容each_title = "" # 初始化each_url = "" # 初始化splits_num = len(url_buf.split(" ")) # 以空格分割字符串if(splits_num > 3): # 有多余空格,說明標題里含有空格了each_title = url_buf.split(" ")[0] + url_buf.split(" ")[-2] # 拼接標題else:each_title = url_buf.split(" ")[0] + url_buf.split(" ")[1] # 拼接標題each_title = re.sub(r'[\|\/\<\>\:\*\?\\\"]', "_", each_title) # 剔除不合法字符filepath = rootpath + "/" + each_title # 為每篇文章創建文件夾if(not os.path.exists(filepath)): # 若不存在,則創建文件夾os.makedirs(filepath)os.chdir(filepath) # 切換至文件夾each_url = url_buf.split(" ")[-1] # 獲得文章URLheaders = {'User-Agent': r'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',}html = requests.get(each_url, headers=headers)soup = BeautifulSoup(html.text, 'lxml')article = soup.find(class_="article").find_all("p") # 查找文章內容位置img_urls = soup.find("article").find_all("img") # 獲得文章圖片URL集print("*" * 60)print(each_title)print(">> 保存文檔 - ", end="")for i in article:line_content = i.get_text() # 獲取標簽內的文本# print(line_content)if(line_content != None): # 文本不為空with open(each_title+r'.txt', 'a+', encoding='utf-8') as fp:fp.write(line_content + "\n") # 寫入本地文件fp.close()print("完畢!")print(">> 保存圖片 - %d張" % len(img_urls), end="")for i in range(len(img_urls)):pic_down = requests.get(img_urls[i]["src"])with open(str(i)+r'.jpeg', 'ab+') as fp:fp.write(pic_down.content)fp.close()print("完畢!\r\n")global rootpath # 全局變量,存放路徑 if __name__ == '__main__':# url = "https://www.sohu.com/a/290059377_479499?sec=wd"# html = requests.get(url)# soup = BeautifulSoup(html.text, 'lxml')# img = soup.find("article").find_all("img")# print(img)# print(img[0]["src"])url = input("輸入地址,(不輸入則默認為機甲同盟個人主頁):")if(url == ""):url = "https://mp.sohu.com/profile?xpt=b1NlSFRzMGJ5Sl84dnh2ZllseHMyMGxsejFVSUB3ZWNoYXQuc29odS5jb20="xpt = url.split("=")[1]html = requests.get(url)soup = BeautifulSoup(html.text, 'lxml')name = soup.find(class_="profile_title").get_text().strip() # 查找搜狐號print("*"*60)print("URL => ", url)print("搜狐號 => ", name)print("*" * 60)print("\r\n")rootpath = os.getcwd() + r"/spider/" + nameif(not os.path.exists(rootpath)): # 若不存在,則創建文件夾os.makedirs(rootpath)os.chdir(rootpath) # 切換至文件夾url_buf = get_url(xpt)for i in url_buf:get_content(i)print("\r\n>> 程序結束!<<")?
總結
以上是生活随笔為你收集整理的详解爬取搜狐号自媒体的所有文章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis 如何链接mysql_如何连接
- 下一篇: afuwin64教程_afuwin64位