【发布时间】:2021-06-14 20:02:30
【问题描述】:
项目:wordpress-plugins 的元数据列表: - 大约有 50 个插件感兴趣!但挑战是:我想获取所有现有插件的元数据。我随后想要在获取后过滤掉的是 - 那些具有最新时间戳的插件 - 最近更新(最近)。这一切都是为了 aobut acutality...所以开始的基本 URL 是这样的:
url = "https://wordpress.org/plugins/browse/popular/
目标:我想获取我们在流行插件的前 50 页上找到的插件的所有元数据......例如......:
https://wordpress.org/plugins/wp-job-manager
https://wordpress.org/plugins/ninja-forms
https://wordpress.org/plugins/participants-database ....and so on and so forth.
我们开始:
import requests
from bs4 import BeautifulSoup
from concurrent.futures.thread import ThreadPoolExecutor
url = "https://wordpress.org/plugins/browse/popular/{}"
def main(url, num):
with requests.Session() as req:
print(f"Collecting Page# {num}")
r = req.get(url.format(num))
soup = BeautifulSoup(r.content, 'html.parser')
link = [item.get("href")
for item in soup.findAll("a", rel="bookmark")]
return set(link)
with ThreadPoolExecutor(max_workers=20) as executor:
futures = [executor.submit(main, url, num)
for num in [""]+[f"page/{x}/" for x in range(2, 50)]]
allin = []
for future in futures:
allin.extend(future.result())
def parser(url):
with requests.Session() as req:
print(f"Extracting {url}")
r = req.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
target = [item.get_text(strip=True, separator=" ") for item in soup.find(
"h3", class_="screen-reader-text").find_next("ul").findAll("li")[:8]]
head = [soup.find("h1", class_="plugin-title").text]
new = [x for x in target if x.startswith(
("V", "Las", "Ac", "W", "T", "P"))]
return head + new
with ThreadPoolExecutor(max_workers=50) as executor1:
futures1 = [executor1.submit(parser, url) for url in allin]
for future in futures1:
print(future.result())
这样运行 - 但会返回一些错误..(见下文)
Extracting https://wordpress.org/plugins/use-google-libraries/
Extracting https://wordpress.org/plugins/blocksy-companion/
Extracting https://wordpress.org/plugins/cherry-sidebars/
Extracting https://wordpress.org/plugins/accesspress-social-share/Extracting https://wordpress.org/plugins/goodbye-captcha/
Extracting https://wordpress.org/plugins/wp-whatsapp/
这里是错误的追溯:
Some characters could not be decoded, and were replaced with REPLACEMENT CHARACTER.
Traceback (most recent call last):
File "C:\Users\rob\.spyder-py3\dev\untitled0.py", line 51, in <module>
print(future.result())
File "C:\Users\rob\devel\IDE\lib\concurrent\futures\_base.py", line 432, in result
return self.__get_result()
File "C:\Users\rob\devel\IDE\lib\concurrent\futures\_base.py", line 388, in __get_result
raise self._exception
File "C:\Users\rob\devel\IDE\lib\concurrent\futures\thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "C:\Users\rob\.spyder-py3\dev\untitled0.py", line 39, in parser
target = [item.get_text(strip=True, separator=" ") for item in soup.find(
AttributeError: 'NoneType' object has no attribute 'find_next'
更新:如上所述,我得到了这个 AttributeError,它说 NoneType 没有属性 find_next。下面是产生令人讨厌的问题的行。
target = [item.get_text(strip=True, separator=" ") for item in soup.find("h3", class_="screen-reader-text").find_next("ul").findAll("li")]
具体来说,问题出在 soup.find() 方法中,该方法可以返回具有 .find_next() 方法(即属性)的 Tag(当它找到某些东西时)或 None(当它没有时)找到任何东西),但没有。我们可以尝试将整个调用提取到它自己的变量中,然后我们可以对其进行测试。
tag = soup.find("h3", class_="screen-reader-text")
target = []
if tag:
lis = tag.find_next("ul").findAll("li")
target = [item.get_text(strip=True, separator=" ") for item in lis[:8]]
顺便说一句;我们可以使用 CSS 选择器来运行它:
target = [item.get_text(strip=True, separator=" ") for item in soup.select("h3.screen-reader-text + ul li")[:8]]
这会得到“ul 下的所有 li,它与屏幕阅读器文本类紧邻 h3”。如果我们希望 li 直接位于 ul 之下(通常无论如何都是这样,但其他元素并非总是如此),我们可以使用 ul > li 代替(> 表示“直接子元素”)。
注意:最好的办法是将所有结果转储到 csv 文件中,或者 - 在屏幕上打印出来。
期待您的来信
【问题讨论】:
-
为什么说你有一个 UTF-8 错误而你有
AttributeError: 'NoneType' object has no attribute 'find_next'这基本上意味着你没有得到你认为你得到的 HTML。 -
对 - 你是对的 - 返工后我发现我在代码中有一些问题:我收到一个 AttributeError,它说 NoneType 没有属性 find_next。下面是给出问题的行:'target = [item.get_text(strip=True, separator="") for item in soup.find("h3", class_="screen-reader-text").find_next( "ul").findAll("li")´
标签: python wordpress beautifulsoup