问题
我这人是有收集的爱好的,喜欢收集一些高质量的信息,在非AI时代如此,在AI时代更是如此。
信息源是网络博客还好,很容易就可以爬取下来了,这里就以阳志平老师的个人博客为例。使用Firecrawl只需要不到30行代码就可以全部爬取。
from firecrawl import FirecrawlApp
import json
app = FirecrawlApp(
api_key="YOUR_API_KEY"
)
params = {
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Referer": "https://www.google.com/"
},
"formats": ["markdown"],
}
url = "https://yangzhiping.com"
links = app.map_url(url)
len(links["links"])
scrape_result = app.batch_scrape_urls(links["links"], params)
with open("results.json" , 'w', encoding="utf-8") as f:
json.dump(scrape_result, f, indent=4, ensure_ascii=False)
但我要是喜欢的是一个公众号的内容,怎么办呢?
公众号的内容就没法这么容易直接进行爬取了,目前一个比较好的方案是利用标签来“半人工”的批量爬取。
基本流程
文章获取
我们都知道公众号的文章是可以在浏览器打开的,比如阳老师公众号里的这篇文章就可以直接在浏览器中打开:2024年读书札记。
当然,我们也是可以直接使用爬虫来进行爬取的,代码和效果如下:
from firecrawl import FirecrawlApp
import json
app = FirecrawlApp(
api_key="YOUR_API_KEY"
)
params = {
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Referer": "https://www.google.com/"
},
"formats": ["markdown"],
}
url = "https://mp.weixin.qq.com/s/FhrMdHByeqVglMzAxOue7A"
scrape_result = app.scrape_url(url, params)
with open("results.json" , 'w', encoding="utf-8") as f:
json.dump(scrape_result, f, indent=4, ensure_ascii=False)
标签页面的HTML获取
在这篇文章的最下面,我们可以看到一个标签。
点进去, 就可以看到这个标签下的全部文章了。
所以说...我们能不能通过这个页面来批量的爬取带有这个标签的所有文章呢?
答案自然是可以的!
打开开发者选项,复制整个HTML元素。
保存进一个文件中,我这里是target.html 。
标签文章的爬取
接下来就可以提取所有带该标签的文章的URL啦~这个任务可以交给下面的Python代码来进行解析来完成:
from bs4 import BeautifulSoup
import json
with open("target.html", "r", encoding="utf-8") as f:
html_content = f.read()
soup = BeautifulSoup(html_content, "html.parser")
ul = soup.find("ul", class_="album__list")
result = []
for li in ul.find_all("li", class_="album__list-item"):
title = li.get("data-title")
link = li.get("data-link")
if title and link:
result.append({"title": title, "url": link})
json_result = json.dumps(result, ensure_ascii=False, indent=4)
print(json_result)
len(json_result)
随后进行批量爬取就可以得到结果了:
from firecrawl import FirecrawlApp
import json
app = FirecrawlApp(
api_key="YOU_API_KEY",
)
params = {
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Referer": "https://www.google.com/"
},
"formats": ["markdown"],
}
docs = []
for item in result:
docs.append(item["url"])
scrape_result = app.batch_scrape_urls(docs, params)
with open("results.json" , 'w', encoding="utf-8") as f:
json.dump(scrape_result, f, indent=4, ensure_ascii=False)
完整代码
完整的代码如下:
from bs4 import BeautifulSoup
import json
from firecrawl import FirecrawlApp
# 注意先获取标签页面的和HTML
with open("target.html", "r", encoding="utf-8") as f:
html_content = f.read()
soup = BeautifulSoup(html_content, "html.parser")
ul = soup.find("ul", class_="album__list")
result = []
for li in ul.find_all("li", class_="album__list-item"):
title = li.get("data-title")
link = li.get("data-link")
if title and link:
result.append({"title": title, "url": link})
docs_link = []
for item in result:
docs_link.append(item["url"])
app = FirecrawlApp(
api_key="YOUR_API_KEY"
)
params = {
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Referer": "https://www.google.com/"
},
"formats": ["markdown"]
}
docs_result = app.batch_scrape_urls(docs_link[:2],params=params)
with open("results.json" , 'w', encoding="utf-8") as f:
json.dump(docs_result, f, indent=4, ensure_ascii=False)
可能的问题
- Q:为什么不直接让爬虫在文章页面就自动提取所有标签的链接并进行自动化的解析,而是需要手动复制整个HTML元素?
A:当然是可以让爬虫进行这样的自动化解析的!我这里为了方便就不去再写一个爬虫来让标签页面加载完整的页面后再去解析了。 - Q:Firecrawl好贵,能不能自己写个爬虫来完成页面爬取的工作呢?
A:这自然也是可以的,其实只要是可以爬取文章的爬虫都可以替代Firecrawl进行爬取,我这里使用Firecrawl的原因一个是我自己部署的有Firecrawl,还有一个点是Firecrawl确实好用。不过官方的部署文档写的是很差劲的,打算未来某一天写一个Firecrawl的部署教程(前提是没有出现更好用的开源爬虫!) - Q:我想爬的公众号从来不打标签怎么办?
A:凉拌!