互聯(lián)網(wǎng)時代,獲取和整理大量的文章內(nèi)容是非常必要的。而PHP作為一種強大的編程語言,可以幫助我們高效地采集文章。本文將分享我在使用PHP進行文章采集過程中的經(jīng)驗和技巧。
1.確定采集目標:
在開始采集之前,我們首先需要明確我們想要采集的文章來源和具體內(nèi)容。可以選擇一些優(yōu)質(zhì)的網(wǎng)站或博客作為目標,提前了解其頁面結(jié)構(gòu)和數(shù)據(jù)格式。
2.使用HTTP請求庫:
在PHP中,我們可以使用curl或者Guzzle等HTTP請求庫來發(fā)送請求并獲取網(wǎng)頁內(nèi)容。這些庫可以幫助我們模擬瀏覽器行為,獲取到完整的頁面源碼。
3.解析HTML:
獲取到頁面源碼后,我們需要使用HTML解析庫(如Simple HTML DOM)來解析HTML結(jié)構(gòu),提取出我們所需的文章標題、正文、作者等信息。
4.處理編碼問題:
在進行HTML解析時,經(jīng)常會遇到編碼問題。我們需要注意判斷網(wǎng)頁的字符編碼,并進行相應的處理,以保證獲取到正確的文本內(nèi)容。
5.過濾無用信息:
有些網(wǎng)頁中可能包含一些廣告、導航欄等無用信息。我們可以使用正則表達式或者CSS選擇器來過濾掉這些干擾項,只保留我們所需的文章內(nèi)容。
6.處理分頁:
如果目標網(wǎng)站的文章分頁展示,我們需要處理分頁問題??梢酝ㄟ^分析URL規(guī)律或者使用分頁參數(shù)來獲取多頁的文章內(nèi)容。
7.存儲數(shù)據(jù):
獲取到文章內(nèi)容后,我們可以選擇將其存儲到數(shù)據(jù)庫中,或者生成JSON、XML等格式的文件進行保存。這樣方便后續(xù)的數(shù)據(jù)處理和展示。
8.定時任務:
如果我們需要定期采集文章,可以使用PHP的定時任務工具(如cron)來自動執(zhí)行采集程序,保證數(shù)據(jù)的及時更新。
9.異常處理:
在采集過程中,可能會遇到網(wǎng)絡(luò)異常、頁面結(jié)構(gòu)變化等問題。我們需要編寫健壯的代碼,并進行適當?shù)漠惓L幚恚源_保程序的穩(wěn)定性和可靠性。
10.合法合規(guī):
在進行文章采集時,要遵守相關(guān)法律法規(guī)和網(wǎng)站的規(guī)定。尊重原創(chuàng)作者的權(quán)益,不侵犯他人的合法權(quán)益。
以上是我在使用PHP進行文章采集過程中總結(jié)出的經(jīng)驗和技巧。希望對大家在實際應用中有所幫助。通過合理利用PHP的強大功能,我們可以高效地獲取和整理大量的文章內(nèi)容,為自己的工作和學習提供有力支持。
者:kingname
Gne[1]雖然在提取新聞正文的時候,準確率比較高,但由于提取新聞發(fā)布時間使用的是正則表達式,因此提取效果有時候不那么讓人滿意。
最近我發(fā)現(xiàn)Python的一個第三方庫,叫做htmldate,經(jīng)過測試,它提取新聞的發(fā)布時間比較準確。我們來看看這個庫怎么使用。首先使用pip安裝:
python3 -m pip install htmldate1.
然后,我們使用Requests或者Selenium獲得網(wǎng)站的源代碼:
import requests
from htmldate import find_date
html=requests.get('https://www.kingname.info/2022/03/09/this-is-gnelist/').content.decode('utf-8')
date=find_date(html)
print(date)1.2.3.4.5.
運行效果如下圖所示:
而這篇文章的發(fā)布時間,確實是3月9號:
我們再用網(wǎng)易新聞來看一下,相互激勵 增進友誼(精彩綻放) |殘奧|中國代表團|單板滑雪|奪金_網(wǎng)易政務[2] 這篇新聞對應的發(fā)布時間如下圖所示:
現(xiàn)在我們用Requests獲得它的源代碼,然后再提取發(fā)布時間:
發(fā)布日期確實對了,但是后面的時間怎么丟失了呢?如果想把時分秒保留下來,可以增加一個參數(shù)outputformat,它的值就是你在datetime.strftime里面輸入的值:
find_date(html, outputformat='%Y-%m-%d %H:%M:%S')1.
運行效果如下圖所示:
find_date的參數(shù),除了網(wǎng)頁源代碼外,還可以傳入URL,或者是lxml里面的Dom對象,例如:
from lxml.html import fromstring
selector=fromstring(html)
date=find_date(selector)1.2.3.4.
參考文獻
[1] Gne: https://github.com/GeneralNewsExtractor/GeneralNewsExtractor
[2] 相互激勵 增進友誼(精彩綻放) |殘奧|中國代表團|單板滑雪|奪金_網(wǎng)易政務: https://www.163.com/news/article/H28Q6NQ1000189FH.html
來源: 未聞Code
就在昨天,豆醬的某乎在第二次15天禁言之后,又被有計劃的禁言了15天,也就是說截止昨天(2020/3/27),豆醬因為之前的評論已經(jīng)被禁言過7+15天,并將再加未來15天??梢娺@個并不是一時沖動的行為,而是有計劃的。首先我相信某乎的公正性,也感謝做這個事情的人沒對我的號做什么。 但是作為對豆醬昨天被禁言的回應,今天我的文章會調(diào)整一下。原計劃是給大家科普自然語言處理(NLP)和文本分類,但今天我會先放出我B站視頻展示的約600篇文章是如何爬取的技術(shù)文。
最后我想對那些不喜歡我的人說:我是個技術(shù)人,我開始嘗試做內(nèi)容是希望讓大家展示好玩的技術(shù),吸引大家學習知識。雖然我寫的文章和視頻引起了爭議,但是我一直希望跟大家講解的如何獲得和爬取數(shù)據(jù),如何分析,我的結(jié)論是如何獲得的,希望大家喜歡這樣探討問題的方法。我雖然有自己的觀點,我夫人也喜歡肖戰(zhàn),但我們并不想針對或死磕任何人。 你們正在使用你們所不齒的方法針對我們。 古話有云:己所不欲勿施于人。
文章無圖有料,不懂技術(shù)的各位也應該仔細瞧瞧。
在之前的文章中,我已經(jīng)和大家分享了如何直接爬取AO3的文章,那么如何找到文章的關(guān)聯(lián)關(guān)系是一件比較頭疼的問題。如果自己去寫爬蟲會比較浪費資源。最省事的方法就是借助搜索引擎進行資料獲取。這里,我們就以 lofter 到 AO3 的外鏈為例。
加載的函數(shù)庫還是與之前相同,這里我不再復述。
import sys
import re
import os
import time
from tqdm import tqdm
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from bs4 import BeautifulSoup
import random
這里和大家科普一下搜索引擎的高級搜索模式,平時大家使用搜索引擎,可能都是一整句話放進去搜索。但實際上搜索引擎是支持一定的高級語法以方便獲取到更高級的內(nèi)容。我們以谷歌為例:
“”精確匹配
使用引號來搜索一個完全匹配的字詞或一組字詞。在搜索歌詞或文學作品中的一段文字時,此選項很實用。建議您只在查找非常確切的字詞或詞組時使用該功能,否則可能會無意中排除掉有用的搜索結(jié)果。
例如“見與不見” 搜索結(jié)果精確匹配“見與不見”,不能拆分成“見”與“不見”。
-排除字詞
在某個字詞前添加短橫 (-) 可排除所有包含該字詞的搜索結(jié)果。
例如:大熊貓 -百科 搜索結(jié)果中不出現(xiàn)“百科”
OR選擇性字詞搜索
選擇性字詞OR搜索結(jié)果匹配多個搜索字詞中的任意一個。沒有OR搜索結(jié)果中通常只會顯示與多個字詞都匹配的網(wǎng)頁。
例如:奧運會 2014 OR 2018 搜索結(jié)果中會出現(xiàn) “奧運會 2014”或者“奧運會 2018”的結(jié)果
site在特定網(wǎng)站或域名中搜索
在搜索中加入“site:”可以限定在某個特定網(wǎng)站中搜索信息
例如:LOFTER site:lofter.com
“site:”后面跟的站點域名,不要帶“http://”。site:和站點名之間,不要帶空格。
inurl在特定url鏈接中搜索
在搜索中加入“inurl:”可以限定在網(wǎng)站url鏈接中搜索網(wǎng)站信息
例如:auto視頻教程 inurl:video
搜索詞“auto視頻教程”是可以出現(xiàn)在網(wǎng)頁的任何位置,而“video”則必須出現(xiàn)在網(wǎng)頁url中。
以上只是谷歌的部分高級搜索語法,百度也有類似的使用方法,大家可以自己去查查詳細的使用方法。我們這里用到了 site: 標簽 和 inurl: 標簽 也就是:
site:lofter.com inurl:ao3
這條語句的含義是,在 lofter.com 中 搜索 含有 ao3 鏈接 的結(jié)果。這里需要注意,實際搜索過程中,"ao3" 需要換成該網(wǎng)站的實際域名。這里因為不想透露真實網(wǎng)站地址所以使用了 "ao3" 替代。
分析url 的思路我在 《我是怎樣得到AO3內(nèi)容的》 有介紹過,這里直接給結(jié)論。谷歌的url 由 search?后的內(nèi)容構(gòu)成:
這里說明一下,我確實專門搜索了語言為英文的頁面,但搜索引擎的模糊性使得結(jié)果依然有大部分是中文文章。但是我可以證明兩點:
言歸正傳看代碼:
#獲谷歌取搜索頁面
def make_google_search_url(page=0, num=100):
base_loc='https://www.google.com/search?hl=en&q=site:lofter.com+inurl:ao3&safe=images'
base_loc +="&num="+str(num)
base_loc +="&start="+str(page*num) #搜索頁
return base_loc
獲取鏈接的方法依然是 chrome 瀏覽器調(diào)試模式(F12)分析元素并用 BeautifulSoup 解析,這里不再復述,大家直接看代碼。
#從谷歌獲取文章鏈接
def get_url_from_search(html):
old_list=[]
soup=BeautifulSoup(html, 'html.parser')
search_div=soup.find('div', attrs={'id': 'search'})
div_g_groups=search_div.findAll('div', attrs={'class': 'g'})
for g in div_g_groups:
div_r=g.find('div', attrs={'class': 'r'})
a_hurl=div_r.find('a')
old_list.append(a_hurl['href'])
return old_list
最后就是判斷 lofter 的頁面中是否含有 有效的 ao3 鏈接。按照之前的經(jīng)驗,判定含有 works 的 url 才考慮為有外鏈文章。但是在后來實踐過程中 發(fā)現(xiàn)含有 users 的外鏈也非常有意思,就一并保存了。
保存的內(nèi)容有: lofter 頁面,本 lofter 頁面中所有含有 ao3 外鏈的鏈接,所有涉及的 ao3 原文頁面,ao3 用戶介紹頁(內(nèi)含該用戶所有文章)
注意,目前目前我只是保存了 ao3 用戶介紹頁(如果有)。并沒有進行二次爬取或分析。
另外相比 《我是怎樣得到AO3內(nèi)容的》中的函數(shù),這里進行了優(yōu)化,當出現(xiàn)“Retry later”時,函數(shù)會自動重試,而不會想之前就直接把這一頁放過不保存了。
代碼中 ao3 站點地址我使用 xxx 代替。
def find_ao3_from_lofter(lofter_url_list, browser, path):
for url in lofter_url_list:
print(url)
dir_name=(
url.replace("http://", "")
.replace(".com/", "_")
.replace("/", "_")
.replace(".", "_")
)
dir_path=os.path.join(path, dir_name)
isExists=os.path.exists(dir_path)
if isExists:
print("Exists")
continue
# 判斷結(jié)果
ao3_links=[]
browser.get(url)
currurl=browser.current_url
if "xxx" in currurl and (
"/works/" in currurl or "/users/" in currurl
): # 如果url 直接跳轉(zhuǎn)
ao3_links.append(currurl)
lhtml=""
else: # 沒有跳轉(zhuǎn)
lhtml=browser.page_source
soup=BeautifulSoup(lhtml, "html.parser")
alink_groups=soup.findAll("a", attrs={"rel": "nofollow"})
for alink in alink_groups:
href_str=alink["href"]
if "xxx" in href_str and (
"/works/" in href_str or "/users/" in href_str
):
ao3_links.append(href_str)
if ao3_links:
# 判斷路徑是否存在
isExists=os.path.exists(dir_path)
# 如果不存在則創(chuàng)建目錄
os.makedirs(dir_path)
links_str=url + "\n"
need_agree=True
for work_url in ao3_links: # 遍歷ao3鏈接
links_str +=work_url + "\n"
print(os.path.join(dir_path, "links.txt"))
fh=open(os.path.join(dir_path, "links.txt"), "w") # 保存頁面
fh.write(links_str) # 寫入內(nèi)容
fh.close() # 關(guān)閉
print(os.path.join(dir_path, "lofter.html"))
fh=open(os.path.join(dir_path, "lofter.html"), "w") # 保存頁面
fh.write(lhtml) # 寫入內(nèi)容
fh.close() # 關(guān)閉
for work_url in ao3_links:
browser.get(work_url)
if need_agree:
try:
time.sleep(3)
browser.find_element_by_id("tos_agree").click()
time.sleep(1)
browser.find_element_by_id("accept_tos").click()
time.sleep(1)
need_agree=False
except NoSuchElementException:
need_agree=False
work_html_text=browser.page_source # 獲得頁面代碼
work_name=(
work_url.replace("https://", "")
.replace("http://", "")
.replace("xxx", "")
.replace(".com/", "")
.replace(".org/", "")
.replace("/", "_")
.replace(".", "_")
.replace("#", "_")
)
work_path=os.path.join(dir_path, work_name + ".html")
if (
'If you accept cookies from our site and you choose "Proceed"'
in work_html_text
): # 無法獲取正文則點擊Proceed
browser.find_element_by_link_text("Proceed").click()
time.sleep(1)
browser.get(work_url)
work_html_text=browser.page_source
if "Retry later" in work_html_text:
while "Retry later" in work_html_text:
print(work_path)
fh=open(work_path, "w") # 保存頁面
fh.write("Need_to_reload") # 寫入內(nèi)容
fh.close() # 關(guān)閉
print("Retry Later")
time.sleep(3)
browser.get("http://www.baidu.com")
time.sleep(3)
browser.quit()
c_service.stop()
time.sleep(60)
c_service.start()
browser=webdriver.Chrome(
chrome_options=chrome_options
) # 調(diào)用Chrome瀏覽器
browser.get("https://xxx.org/")
time.sleep(5)
browser.find_element_by_id("tos_agree").click()
time.sleep(2)
browser.find_element_by_id("accept_tos").click()
time.sleep(3)
browser.get(work_url)
work_html_text=browser.page_source # 獲得頁面代碼
if (
'If you accept cookies from our site and you choose "Proceed"'
in work_html_text
): # 無法獲取正文則點擊Proceed
browser.find_element_by_link_text("Proceed").click()
time.sleep(1)
browser.get(work_url)
work_html_text=browser.page_source
# if "<!--chapter content-->" in work_html_text:
print(work_path)
fh=open(work_path, "w") # 保存頁面
fh.write(work_html_text) # 寫入內(nèi)容
fh.close() # 關(guān)閉
time.sleep(float(random.randint(10, 50)) / 10) # 隨機延時
return browser
設(shè)置起止頁
start_p=0
end_p=4
如果平凡使用谷歌,谷歌會啟動防機器人機制,這是函數(shù)會暫停等待我人工解鎖的。
所以這里我也相當于解釋了我為什么沒有翻墻,因為如果我使用翻墻軟件爬取,是會被谷歌發(fā)現(xiàn)并封殺掉的,而如何繞過呢?賣個關(guān)子,看看有沒有懂行的朋友幫大家解釋一下。
c_service=webdriver.chrome.service.Service("/usr/bin/chromedriver")
c_service.command_line_args()
c_service.start()
chrome_options=webdriver.ChromeOptions()
# chrome_options.add_argument('--proxy-server=socks5://localhost:1080')
auto_quit_cnt=0
browser=webdriver.Chrome(chrome_options=chrome_options) # 調(diào)用Chrome瀏覽器
for page in range(start_p, end_p):
print("-" * 30)
print("Page: " + str(page))
print("-" * 30)
google_search_url=make_google_search_url(page)
browser.get(google_search_url)
html_text=browser.page_source # 獲得頁面代碼
while "Our systems have detected unusual traffic" in html_text:
print("Google Robot!")
time.sleep(10)
html_text=browser.page_source # 獲得頁面代碼
auto_quit_cnt +=1
if auto_quit_cnt > 30:
break
auto_quit_cnt=0
lofter_list=get_url_from_search(html_text)
browser=find_ao3_from_lofter(lofter_list, browser, "lofter")
關(guān)于AO3這個系列,我還剩最后兩篇文章:
這個話題做了快一個月了,我希望能夠?qū)⑽蚁胫v的技術(shù)安安靜靜講完。然后再帶著大家探索其他有意思的編程技術(shù),而不是揪著這個話題不放。
所以再次申明,我只是分析 AO3 其他事情我不做探討和引申,也懇請大家理性思考和探討。上文中我已經(jīng)有限擴大了討論范圍。我的下一篇文章會按照我的規(guī)劃來,我的下一個視頻會是另一個好玩的技術(shù)。
我也希望即使你不喜歡我,也不要討厭技術(shù),不要討厭學習。
在這段時間之前我是沒有做Python數(shù)據(jù)分析的相關(guān)知識的;雖然同屬深度學習,NLP不是我的專業(yè),所以我也是第一次實踐,但是通過這個熱點,我收獲了很多新知識,也有很多人給我點贊鼓勵交流探討。我收獲了很多。
但是,
你收獲了什么呢?
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。