互联网时代,获取和整理大量的文章内容是非常必要的。而PHP作为一种强大的编程语言,可以帮助我们高效地采集文章。本文将分享我在使用PHP进行文章采集过程中的经验和技巧。
1.确定采集目标:
在开始采集之前,我们首先需要明确我们想要采集的文章来源和具体内容。可以选择一些优质的网站或博客作为目标,提前了解其页面结构和数据格式。
2.使用HTTP请求库:
在PHP中,我们可以使用curl或者Guzzle等HTTP请求库来发送请求并获取网页内容。这些库可以帮助我们模拟浏览器行为,获取到完整的页面源码。
3.解析HTML:
获取到页面源码后,我们需要使用HTML解析库(如Simple HTML DOM)来解析HTML结构,提取出我们所需的文章标题、正文、作者等信息。
4.处理编码问题:
在进行HTML解析时,经常会遇到编码问题。我们需要注意判断网页的字符编码,并进行相应的处理,以保证获取到正确的文本内容。
5.过滤无用信息:
有些网页中可能包含一些广告、导航栏等无用信息。我们可以使用正则表达式或者CSS选择器来过滤掉这些干扰项,只保留我们所需的文章内容。
6.处理分页:
如果目标网站的文章分页展示,我们需要处理分页问题。可以通过分析URL规律或者使用分页参数来获取多页的文章内容。
7.存储数据:
获取到文章内容后,我们可以选择将其存储到数据库中,或者生成JSON、XML等格式的文件进行保存。这样方便后续的数据处理和展示。
8.定时任务:
如果我们需要定期采集文章,可以使用PHP的定时任务工具(如cron)来自动执行采集程序,保证数据的及时更新。
9.异常处理:
在采集过程中,可能会遇到网络异常、页面结构变化等问题。我们需要编写健壮的代码,并进行适当的异常处理,以确保程序的稳定性和可靠性。
10.合法合规:
在进行文章采集时,要遵守相关法律法规和网站的规定。尊重原创作者的权益,不侵犯他人的合法权益。
以上是我在使用PHP进行文章采集过程中总结出的经验和技巧。希望对大家在实际应用中有所帮助。通过合理利用PHP的强大功能,我们可以高效地获取和整理大量的文章内容,为自己的工作和学习提供有力支持。
者:kingname
Gne[1]虽然在提取新闻正文的时候,准确率比较高,但由于提取新闻发布时间使用的是正则表达式,因此提取效果有时候不那么让人满意。
最近我发现Python的一个第三方库,叫做htmldate,经过测试,它提取新闻的发布时间比较准确。我们来看看这个库怎么使用。首先使用pip安装:
python3 -m pip install htmldate1.
然后,我们使用Requests或者Selenium获得网站的源代码:
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.
运行效果如下图所示:
而这篇文章的发布时间,确实是3月9号:
我们再用网易新闻来看一下,相互激励 增进友谊(精彩绽放) |残奥|中国代表团|单板滑雪|夺金_网易政务[2] 这篇新闻对应的发布时间如下图所示:
现在我们用Requests获得它的源代码,然后再提取发布时间:
发布日期确实对了,但是后面的时间怎么丢失了呢?如果想把时分秒保留下来,可以增加一个参数outputformat,它的值就是你在datetime.strftime里面输入的值:
find_date(html, outputformat='%Y-%m-%d %H:%M:%S')1.
运行效果如下图所示:
find_date的参数,除了网页源代码外,还可以传入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] 相互激励 增进友谊(精彩绽放) |残奥|中国代表团|单板滑雪|夺金_网易政务: https://www.163.com/news/article/H28Q6NQ1000189FH.html
来源: 未闻Code
就在昨天,豆酱的某乎在第二次15天禁言之后,又被有计划的禁言了15天,也就是说截止昨天(2020/3/27),豆酱因为之前的评论已经被禁言过7+15天,并将再加未来15天。可见这个并不是一时冲动的行为,而是有计划的。首先我相信某乎的公正性,也感谢做这个事情的人没对我的号做什么。 但是作为对豆酱昨天被禁言的回应,今天我的文章会调整一下。原计划是给大家科普自然语言处理(NLP)和文本分类,但今天我会先放出我B站视频展示的约600篇文章是如何爬取的技术文。
最后我想对那些不喜欢我的人说:我是个技术人,我开始尝试做内容是希望让大家展示好玩的技术,吸引大家学习知识。虽然我写的文章和视频引起了争议,但是我一直希望跟大家讲解的如何获得和爬取数据,如何分析,我的结论是如何获得的,希望大家喜欢这样探讨问题的方法。我虽然有自己的观点,我夫人也喜欢肖战,但我们并不想针对或死磕任何人。 你们正在使用你们所不齿的方法针对我们。 古话有云:己所不欲勿施于人。
文章无图有料,不懂技术的各位也应该仔细瞧瞧。
在之前的文章中,我已经和大家分享了如何直接爬取AO3的文章,那么如何找到文章的关联关系是一件比较头疼的问题。如果自己去写爬虫会比较浪费资源。最省事的方法就是借助搜索引擎进行资料获取。这里,我们就以 lofter 到 AO3 的外链为例。
加载的函数库还是与之前相同,这里我不再复述。
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
这里和大家科普一下搜索引擎的高级搜索模式,平时大家使用搜索引擎,可能都是一整句话放进去搜索。但实际上搜索引擎是支持一定的高级语法以方便获取到更高级的内容。我们以谷歌为例:
“”精确匹配
使用引号来搜索一个完全匹配的字词或一组字词。在搜索歌词或文学作品中的一段文字时,此选项很实用。建议您只在查找非常确切的字词或词组时使用该功能,否则可能会无意中排除掉有用的搜索结果。
例如“见与不见” 搜索结果精确匹配“见与不见”,不能拆分成“见”与“不见”。
-排除字词
在某个字词前添加短横 (-) 可排除所有包含该字词的搜索结果。
例如:大熊猫 -百科 搜索结果中不出现“百科”
OR选择性字词搜索
选择性字词OR搜索结果匹配多个搜索字词中的任意一个。没有OR搜索结果中通常只会显示与多个字词都匹配的网页。
例如:奥运会 2014 OR 2018 搜索结果中会出现 “奥运会 2014”或者“奥运会 2018”的结果
site在特定网站或域名中搜索
在搜索中加入“site:”可以限定在某个特定网站中搜索信息
例如:LOFTER site:lofter.com
“site:”后面跟的站点域名,不要带“http://”。site:和站点名之间,不要带空格。
inurl在特定url链接中搜索
在搜索中加入“inurl:”可以限定在网站url链接中搜索网站信息
例如:auto视频教程 inurl:video
搜索词“auto视频教程”是可以出现在网页的任何位置,而“video”则必须出现在网页url中。
以上只是谷歌的部分高级搜索语法,百度也有类似的使用方法,大家可以自己去查查详细的使用方法。我们这里用到了 site: 标签 和 inurl: 标签 也就是:
site:lofter.com inurl:ao3
这条语句的含义是,在 lofter.com 中 搜索 含有 ao3 链接 的结果。这里需要注意,实际搜索过程中,"ao3" 需要换成该网站的实际域名。这里因为不想透露真实网站地址所以使用了 "ao3" 替代。
分析url 的思路我在 《我是怎样得到AO3内容的》 有介绍过,这里直接给结论。谷歌的url 由 search?后的内容构成:
这里说明一下,我确实专门搜索了语言为英文的页面,但搜索引擎的模糊性使得结果依然有大部分是中文文章。但是我可以证明两点:
言归正传看代码:
#获谷歌取搜索页面
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 浏览器调试模式(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 链接。按照之前的经验,判定含有 works 的 url 才考虑为有外链文章。但是在后来实践过程中 发现含有 users 的外链也非常有意思,就一并保存了。
保存的内容有: lofter 页面,本 lofter 页面中所有含有 ao3 外链的链接,所有涉及的 ao3 原文页面,ao3 用户介绍页(内含该用户所有文章)
注意,目前目前我只是保存了 ao3 用户介绍页(如果有)。并没有进行二次爬取或分析。
另外相比 《我是怎样得到AO3内容的》中的函数,这里进行了优化,当出现“Retry later”时,函数会自动重试,而不会想之前就直接把这一页放过不保存了。
代码中 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
# 判断结果
ao3_links=[]
browser.get(url)
currurl=browser.current_url
if "xxx" in currurl and (
"/works/" in currurl or "/users/" in currurl
): # 如果url 直接跳转
ao3_links.append(currurl)
lhtml=""
else: # 没有跳转
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)
# 如果不存在则创建目录
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) # 写入内容
fh.close() # 关闭
print(os.path.join(dir_path, "lofter.html"))
fh=open(os.path.join(dir_path, "lofter.html"), "w") # 保存页面
fh.write(lhtml) # 写入内容
fh.close() # 关闭
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") # 写入内容
fh.close() # 关闭
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
) # 调用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) # 写入内容
fh.close() # 关闭
time.sleep(float(random.randint(10, 50)) / 10) # 随机延时
return browser
设置起止页
start_p=0
end_p=4
如果平凡使用谷歌,谷歌会启动防机器人机制,这是函数会暂停等待我人工解锁的。
所以这里我也相当于解释了我为什么没有翻墙,因为如果我使用翻墙软件爬取,是会被谷歌发现并封杀掉的,而如何绕过呢?卖个关子,看看有没有懂行的朋友帮大家解释一下。
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) # 调用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")
关于AO3这个系列,我还剩最后两篇文章:
这个话题做了快一个月了,我希望能够将我想讲的技术安安静静讲完。然后再带着大家探索其他有意思的编程技术,而不是揪着这个话题不放。
所以再次申明,我只是分析 AO3 其他事情我不做探讨和引申,也恳请大家理性思考和探讨。上文中我已经有限扩大了讨论范围。我的下一篇文章会按照我的规划来,我的下一个视频会是另一个好玩的技术。
我也希望即使你不喜欢我,也不要讨厌技术,不要讨厌学习。
在这段时间之前我是没有做Python数据分析的相关知识的;虽然同属深度学习,NLP不是我的专业,所以我也是第一次实践,但是通过这个热点,我收获了很多新知识,也有很多人给我点赞鼓励交流探讨。我收获了很多。
但是,
你收获了什么呢?
*请认真填写需求信息,我们会在24小时内与您取得联系。