Web Scraping 新闻文章在某些情况下 returns 为空 body
Web Scraping news articles in some cases returns empty body
我只是想从 El Pais 网站档案中抓取几篇文章。我从每篇文章中获取:标题、主题标签和文章 body。每篇文章的 HTML 结构都是相同的,脚本对所有标题和主题标签都是成功的,但是对于某些文章,它根本没有抓取 body。下面我添加了我的代码、完整工作文章的链接以及一些返回空体的文章的链接。你知道怎么修吗?
空body篇不是经常发生的,所以有时可以连续出现3篇空的文章,然后5篇成功的文章,1篇空的,3篇成功的。
工作文章
第1条
https://elpais.com/diario/1990/01/17/economia/632530813_850215.html
第2条
https://elpais.com/diario/1990/01/07/internacional/631666806_850215.html
第三条
https://elpais.com/diario/1990/01/05/deportes/631494011_850215.html
没有 body 的文章
第四条
https://elpais.com/diario/1990/01/23/madrid/633097458_850215.html
第五条
https://elpais.com/diario/1990/01/30/economia/633654016_850215.html
第六条
https://elpais.com/diario/1990/01/03/espana/631321213_850215.html
from bs4 import BeautifulSoup
import requests
#place for the url of the article to be scraped
URL = some_url_of_article_above
#print(URL)
page = requests.get(URL)
soup = BeautifulSoup(page.content, "html.parser")
bodydiv = soup.find("div", id="ctn_article_body")
artbody = bodydiv.find_all("p", class_="")
tagdiv = soup.find("div", id="mod_archivado")
hashtags= tagdiv.find_all("li", class_="w_i | capitalize flex align_items_center")
titlediv = soup.find("div", id="article_header")
title = titlediv.find("h1")
#print title of the article
print(title.text)
#print body of the article
arttext = ""
for par in artbody:
arttext += str(par.text)
print(arttext)
#hastags
tagstring = ""
for hashtag in hashtags:
tagstring += hashtag.text
tagstring += ","
print(tagstring)
提前感谢您的帮助!
问题是 <div class="a_b article_body | color_gray_dark" id="ctn_article_body">
元素内部有一个损坏或不完整的 <b>
标签。查看 html 页面中的代码片段:
<div id="ctn_article_body" class="a_b article_body | color_gray_dark"><p class=""></b>La Asociación Ecologista de Defensa dela Naturaleza (AEDENAT) ha denunciado que las obras de la carretera que cruza la Universidad Complutense desde la carretera de La Coruña hasta Cuatro Caminos se están realizando "sin permisos de ningún tipo" y suponen "la destrucción de zonas de pinar en las cercanías del edificio de Filosofia B".</p>
在第一个 <p></p>
标签之后,有一个 </b>
没有它的一对 <b>
标签。这就是原因,因为“html.parser”失败了。
使用本文,
from bs4 import BeautifulSoup
text = """<div id="ctn_article_body" class="a_b article_body | color_gray_dark"><p class=""></b>La Asociación Ecologista de Defensa de la Naturaleza (AEDENAT) ha denunciado que las obras de la carretera que cruza la Universidad Complutense desde la carretera de La Coruña hasta Cuatro Caminos se están realizando "sin permisos de ningún tipo" y suponen "la destrucción de zonas de pinar en las cercanías del edificio de Filosofia B".</p><div id="elpais_gpt-INTEXT" style="width: 0px; height: 0px; display: none;"></div><p class="">Por su parte, José Luis Garro, tercer teniente de alcalde, ha declarado a EL PAÍS: "Tenemos una autorización provisional del rector de la Universidad Complutense. Toda esa zona, además, está pendiente de un plan especial de reforma interior (PERI). Ésta es sólo una solución provisional".</p><p class="">Según Garro, el trazado de la carretera "ha tenido que dar varias vueltas para no tocar las masas arbóreas", aunque reconoce que se ha hecho "en algunos casos", si bien causando "un daño mínimo".</p><p class="footnote">* Este artículo apareció en la edición impresa del lunes, 22 de enero de 1990.</p></div>"""
soup = BeautifulSoup(text, "html.parser")
print(soup.find("div"))
输出:
<div class="a_b article_body | color_gray_dark" id="ctn_article_body"><p class=""></p></div>
如何解决这个问题?好吧,我又尝试了一个不同的解析器,在这种情况下,我使用了 "lxml" 而不是 "html.parser",并且有效。
它选择了 div,所以只需更改这一行就可以了
soup = BeautifulSoup(text, "lxml")
当然你需要安装这个解析器。
编辑:
正如@moreni123 在下面评论的那样,这个解决方案似乎对某些情况是正确的,但并非对所有情况都是正确的。鉴于此,我将添加另一个也可以工作的选项。
似乎使用Selenium来获取网页会更好,因为有些内容是用JavaScript生成的,而请求不能做到这一点,这不是它的目的。
我打算将 Selenium 与无头 chrome 驱动程序一起使用,
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
# article to fetch
url = "https://elpais.com/diario/1990/01/14/madrid/632319855_850215.html"
driver_options = Options()
driver_options.add_argument("--headless")
driver = webdriver.Chrome(executable_path="path/to/chrome/driver", options=driver_options)
# this is the source code with the js executed
driver.get(url)
page = driver.execute_script("return document.getElementsByTagName('html')[0].innerHTML")
# now, as before we use BeautifulSoup to parse it. Selenium is a
# powerful, tool you could use Selenium for this also
soup = BeautifulSoup(page, "html.parser")
print(soup.select("#ctn_article_body"))
#quiting driver
if driver is not None:
driver.quit()
确保chrome驱动程序的路径是正确的,在这一行
driver = webdriver.Chrome(executable_path="path/to/chrome/driver", options=driver_options)
这里是link到Selenium doc, and to the ChromeDriver。以备不时之需下载。
此解决方案应该有效。至少在你传给我的这篇文章中,它是有效的。
我只是想从 El Pais 网站档案中抓取几篇文章。我从每篇文章中获取:标题、主题标签和文章 body。每篇文章的 HTML 结构都是相同的,脚本对所有标题和主题标签都是成功的,但是对于某些文章,它根本没有抓取 body。下面我添加了我的代码、完整工作文章的链接以及一些返回空体的文章的链接。你知道怎么修吗? 空body篇不是经常发生的,所以有时可以连续出现3篇空的文章,然后5篇成功的文章,1篇空的,3篇成功的。
工作文章 第1条 https://elpais.com/diario/1990/01/17/economia/632530813_850215.html 第2条 https://elpais.com/diario/1990/01/07/internacional/631666806_850215.html 第三条 https://elpais.com/diario/1990/01/05/deportes/631494011_850215.html
没有 body 的文章 第四条 https://elpais.com/diario/1990/01/23/madrid/633097458_850215.html 第五条 https://elpais.com/diario/1990/01/30/economia/633654016_850215.html 第六条 https://elpais.com/diario/1990/01/03/espana/631321213_850215.html
from bs4 import BeautifulSoup
import requests
#place for the url of the article to be scraped
URL = some_url_of_article_above
#print(URL)
page = requests.get(URL)
soup = BeautifulSoup(page.content, "html.parser")
bodydiv = soup.find("div", id="ctn_article_body")
artbody = bodydiv.find_all("p", class_="")
tagdiv = soup.find("div", id="mod_archivado")
hashtags= tagdiv.find_all("li", class_="w_i | capitalize flex align_items_center")
titlediv = soup.find("div", id="article_header")
title = titlediv.find("h1")
#print title of the article
print(title.text)
#print body of the article
arttext = ""
for par in artbody:
arttext += str(par.text)
print(arttext)
#hastags
tagstring = ""
for hashtag in hashtags:
tagstring += hashtag.text
tagstring += ","
print(tagstring)
提前感谢您的帮助!
问题是 <div class="a_b article_body | color_gray_dark" id="ctn_article_body">
元素内部有一个损坏或不完整的 <b>
标签。查看 html 页面中的代码片段:
<div id="ctn_article_body" class="a_b article_body | color_gray_dark"><p class=""></b>La Asociación Ecologista de Defensa dela Naturaleza (AEDENAT) ha denunciado que las obras de la carretera que cruza la Universidad Complutense desde la carretera de La Coruña hasta Cuatro Caminos se están realizando "sin permisos de ningún tipo" y suponen "la destrucción de zonas de pinar en las cercanías del edificio de Filosofia B".</p>
在第一个 <p></p>
标签之后,有一个 </b>
没有它的一对 <b>
标签。这就是原因,因为“html.parser”失败了。
使用本文,
from bs4 import BeautifulSoup
text = """<div id="ctn_article_body" class="a_b article_body | color_gray_dark"><p class=""></b>La Asociación Ecologista de Defensa de la Naturaleza (AEDENAT) ha denunciado que las obras de la carretera que cruza la Universidad Complutense desde la carretera de La Coruña hasta Cuatro Caminos se están realizando "sin permisos de ningún tipo" y suponen "la destrucción de zonas de pinar en las cercanías del edificio de Filosofia B".</p><div id="elpais_gpt-INTEXT" style="width: 0px; height: 0px; display: none;"></div><p class="">Por su parte, José Luis Garro, tercer teniente de alcalde, ha declarado a EL PAÍS: "Tenemos una autorización provisional del rector de la Universidad Complutense. Toda esa zona, además, está pendiente de un plan especial de reforma interior (PERI). Ésta es sólo una solución provisional".</p><p class="">Según Garro, el trazado de la carretera "ha tenido que dar varias vueltas para no tocar las masas arbóreas", aunque reconoce que se ha hecho "en algunos casos", si bien causando "un daño mínimo".</p><p class="footnote">* Este artículo apareció en la edición impresa del lunes, 22 de enero de 1990.</p></div>"""
soup = BeautifulSoup(text, "html.parser")
print(soup.find("div"))
输出:
<div class="a_b article_body | color_gray_dark" id="ctn_article_body"><p class=""></p></div>
如何解决这个问题?好吧,我又尝试了一个不同的解析器,在这种情况下,我使用了 "lxml" 而不是 "html.parser",并且有效。
它选择了 div,所以只需更改这一行就可以了
soup = BeautifulSoup(text, "lxml")
当然你需要安装这个解析器。
编辑:
正如@moreni123 在下面评论的那样,这个解决方案似乎对某些情况是正确的,但并非对所有情况都是正确的。鉴于此,我将添加另一个也可以工作的选项。
似乎使用Selenium来获取网页会更好,因为有些内容是用JavaScript生成的,而请求不能做到这一点,这不是它的目的。
我打算将 Selenium 与无头 chrome 驱动程序一起使用,
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
# article to fetch
url = "https://elpais.com/diario/1990/01/14/madrid/632319855_850215.html"
driver_options = Options()
driver_options.add_argument("--headless")
driver = webdriver.Chrome(executable_path="path/to/chrome/driver", options=driver_options)
# this is the source code with the js executed
driver.get(url)
page = driver.execute_script("return document.getElementsByTagName('html')[0].innerHTML")
# now, as before we use BeautifulSoup to parse it. Selenium is a
# powerful, tool you could use Selenium for this also
soup = BeautifulSoup(page, "html.parser")
print(soup.select("#ctn_article_body"))
#quiting driver
if driver is not None:
driver.quit()
确保chrome驱动程序的路径是正确的,在这一行
driver = webdriver.Chrome(executable_path="path/to/chrome/driver", options=driver_options)
这里是link到Selenium doc, and to the ChromeDriver。以备不时之需下载。
此解决方案应该有效。至少在你传给我的这篇文章中,它是有效的。