如何在 Python 中抓取 javascript 网站?
Posted
技术标签:
【中文标题】如何在 Python 中抓取 javascript 网站?【英文标题】:How to scrape a javascript website in Python? 【发布时间】:2020-12-24 22:56:02 【问题描述】:我正在尝试抓取一个网站。我尝试使用两种方法,但都没有为我提供我正在寻找的完整网站源代码。我正在尝试从下面提供的网站 URL 中抓取新闻标题。
网址:“https://www.todayonline.com/”
这是我尝试过但失败的两种方法。
方法一:靓汤
tdy_url = "https://www.todayonline.com/"
page = requests.get(tdy_url).text
soup = BeautifulSoup(page)
soup # Returns me a html with javascript text
soup.find_all('h3')
### Returns me empty list []
方法 2:硒 + BeautifulSoup
tdy_url = "https://www.todayonline.com/"
options = Options()
options.headless = True
driver = webdriver.Chrome("chromedriver",options=options)
driver.get(tdy_url)
time.sleep(10)
html = driver.page_source
soup = BeautifulSoup(html)
soup.find_all('h3')
### Returns me only less than 1/4 of the 'h3' tags found in the original page source
请帮忙。我尝试过抓取其他新闻网站,这要容易得多。谢谢。
【问题讨论】:
您尝试抓取的网站上的新闻数据是使用 JavaScript 获取的,服务器不会返回。但是在第一个示例中,您只获得了服务器返回的页面——请求和 BeautifulSoup 都不执行 JS。但是,您可以打开 Firefox (Chromium) DevTools 并查看哪些请求从服务器获取数据,然后尝试使用请求来模仿它们。这可能比尝试使用 BeautifulSoup 进行网页抓取更容易。 另见@politicalscientist 的回答。他完全按照我在第一条评论中描述的那样做。 【参考方案1】:您尝试抓取的网站上的新闻数据是使用 JavaScript 从服务器获取的(这称为XHR -- XMLHttpRequest)。它是在页面加载或滚动时动态发生的。所以这个数据不会在服务器返回的页面内返回。
在第一个示例中,您只获得了服务器返回的页面——没有新闻,但是应该使用 JS 来获取它们。 requests 和 BeautifulSoup 都不能执行 JS。
但是,您可以尝试使用 Python 请求重现从服务器获取新闻标题的请求。执行以下步骤:
-
打开浏览器的 DevTools(通常需要按 F12 或 Ctrl+Shift+I kbd>),并查看从服务器获取新闻标题的请求。有时,它甚至比使用 BeautifulSoup 抓取网页更容易。这是屏幕截图(Firefox):
复制请求链接(右键->复制->复制链接),并传递给requests.get(...)
。
获取请求的.json()
。它将返回一个易于使用的字典。为了更好地理解字典的结构,我建议使用pprint
而不是简单的打印。请注意,您必须在使用它之前执行from pprint import pprint
。
以下是从页面上的主要新闻中获取标题的代码示例:
import requests
nodes = requests.get("https://www.todayonline.com/api/v3/news_feed/7")\
.json()["nodes"]
for node in nodes:
print(node["node"]["title"])
如果要抓取标题下的一组新闻,则需要更改请求 URL 中news_feed/
后面的数字(要获取它,您只需在 DevTools 中通过“news_feed”过滤请求并滚动新闻页面向下)。
有时网站可以防止僵尸程序(尽管您尝试抓取的网站没有)。在这种情况下,您可能还需要使用these steps。
【讨论】:
【参考方案2】:我会建议你相当简单的方法,
import requests
from bs4 import BeautifulSoup as bs
page = requests.get('https://www.todayonline.com/googlenews.xml').content
soup = bs(page)
news = [i.text for i in soup.find_all('news:title')]
print(news)
输出
['DBS named world’s best bank by New York-based financial publication',
'Russia has very serious questions to answer on Navalny - UK',
"Exclusive: 90% of China's Sinovac employees, families took coronavirus vaccine - CEO",
'Three militants killed after fatal attack on policeman in Tunisia',
.....]
此外,如果需要,您可以查看 XML 页面以获取更多信息。
附:在抓取任何网站之前始终检查合规性:)
【讨论】:
【参考方案3】:收集包含 Javascript 的网页内容的方法有多种。
-
将
selenium
与 Firefox 网络驱动程序一起使用
使用带有phantomJS
的无头浏览器
使用 REST 客户端或 python requests
库进行 API 调用
您必须先进行研究
【讨论】:
【参考方案4】:您可以通过 API 访问数据(查看“网络”选项卡):
例如,
import requests
url = "https://www.todayonline.com/api/v3/news_feed/7"
data = requests.get(url).json()
【讨论】:
以上是关于如何在 Python 中抓取 javascript 网站?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 抓取网页动态内容(动态 HTML/Javascript 表格)
用于 javascript 生成内容的 Python 网页抓取