【问题标题】:how to get all lines with beautifulsoup如何用beautifulsoup获得所有线条
【发布时间】:2020-09-28 16:24:03
【问题描述】:

我正在从他们的数据转储生成维基百科数据集。他们的页面源预览是这样的:

Wikipedia structure

我想获取整个a 标记行,<a href="enwiki-latest-abstract.xml.gz">enwiki-latest-abstract.xml.gz</a> 23-Sep-2020 08:25 780430373

这样我就可以自己找到相关行,即那些有stub-meta-history 并将此类文件的链接存储在列表中的行,以便我可以使用此列表下载所有相关文件。

在另一种情况下,我想获取基于特定日期的链接

这是我的代码:

soup_dump.find_all('li', {'class': 'file'}, limit = 10)[:4]
files = []

# Search through all files
for file in soup_dump.find_all('a'):
    text = file.text
    if 'stub-meta-history' in text:
        files.append(text)

【问题讨论】:

  • 也许因为你find_all只有10个元素?
  • 可以分享网址吗?
  • 我认为您误解了您的数据。日期和大小不是链接的一部分(无论如何,您可以通过迭代数据来处理日期和大小)
  • 另一个提示:我不明白你的第一行。没有列表元素并且您不保存此数据,因此此行在多种方面都无用;)

标签: python web-scraping beautifulsoup


【解决方案1】:

如果您以后想处理这些数据,我认为pandas dataframe 在这里会做得最好。

这是我的看法:

from datetime import datetime
import pandas as pd
import requests
from bs4 import BeautifulSoup
from tabulate import tabulate

response = requests.get("https://dumps.wikimedia.org/enwiki/latest/").text
soup = BeautifulSoup(response, "html.parser")

all_urls = [
    f"https://dumps.wikimedia.org/enwiki/latest/{a['href']}" for a
    in soup.find_all("a") if a.text != "../"
]


def get_lines(bs4_soup):
    for index, line in enumerate(bs4_soup.getText().split('\n')[4:]):
        if line:
            _, *date_and_time, size = line.strip().split()
            yield [
                all_urls[index],
                parse_date(date_and_time),
                human_readable_size(int(size))
            ]


def human_readable_size(size, decimal_places=2):
    for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']:
        if size < 1024.0 or unit == 'PiB':
            break
        size /= 1024.0
    return f"{size:.{decimal_places}f} {unit}"


def parse_date(date):
    return datetime.strptime(' '.join(date), "%d-%b-%Y %H:%M")


lines = [line for line in get_lines(soup)]

columns = ["URL", "DATE AND TIME", "SIZE"]
df = pd.DataFrame(lines, columns=columns)
df.to_csv("wiki_dump.csv", index=False)
print(tabulate(df[:10], showindex=False, headers=columns))

输出(沿 .csv 文件):

URL                                                                                DATE AND TIME        SIZE
---------------------------------------------------------------------------------  -------------------  ----------
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract.xml.gz            2020-09-23 08:25:00  744.28 MiB
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract.xml.gz-rss.xml    2020-09-23 08:25:00  760.00 B
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract1.xml.gz           2020-09-22 23:28:00  107.15 MiB
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract1.xml.gz-rss.xml   2020-09-23 08:24:00  763.00 B
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract10.xml.gz          2020-09-23 04:14:00  26.75 MiB
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract10.xml.gz-rss.xml  2020-09-23 08:24:00  766.00 B
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract11.xml.gz          2020-09-23 03:32:00  25.00 MiB
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract11.xml.gz-rss.xml  2020-09-23 08:24:00  766.00 B
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract12.xml.gz          2020-09-23 03:59:00  23.40 MiB
https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-abstract12.xml.gz-rss.xml  2020-09-23 08:24:00  766.00 B
and so on...

【讨论】:

  • 这个解决方案听起来很有趣,但是,在这些搜索关键字的情况下,“pages-articles-multistream”最后的行会产生编辑行
  • 另外,"return f"{size:.{decimal_places}f} {unit}"" 有错误
  • 我已经解决了编辑网址的问题。但是,我不确定您所说的“return f"{size:.{decimal_places}f} {unit}" 有错误。您能否提供更多详细信息和回溯?
【解决方案2】:

关键字是next_sibling,通过它你可以到达“下一个元素”。我不知道您如何处理这些数据,但这里有一个示例:

from bs4 import BeautifulSoup
import requests

page = requests.get("https://dumps.wikimedia.org/enwiki/latest/")
soup = BeautifulSoup(page.content, 'html.parser')

# soup.find_all('li', {'class': 'file'}, limit = 10)[:4]
files = []

# Search through all files
for file in soup.find_all('a'):
    text = file["href"]
    if 'stub-meta-history' in text:
        files.append("{} {}".format(text, file.next_sibling.strip()))

for x in files:
    print(x)

示例输出:

enwiki-latest-stub-meta-history.xml.gz 21-Sep-2020 19:04         69246792624
enwiki-latest-stub-meta-history.xml.gz-rss.xml 23-Sep-2020 08:28                 787
enwiki-latest-stub-meta-history1.xml.gz 21-Sep-2020 00:23          2625343450
enwiki-latest-stub-meta-history1.xml.gz-rss.xml 23-Sep-2020 08:27                 790
enwiki-latest-stub-meta-history10.xml.gz 21-Sep-2020 08:28          2782265716
enwiki-latest-stub-meta-history10.xml.gz-rss.xml 23-Sep-2020 08:27                 793
enwiki-latest-stub-meta-history11.xml.gz 21-Sep-2020 08:23          2817413722
enwiki-latest-stub-meta-history11.xml.gz-rss.xml 23-Sep-2020 08:27                 793

【讨论】:

  • 您的解决方案有效,但如果使用这些值“pages-articles-multistream”,则会出现:enwiki-latest-pages-articles-multistream-index12.txt-p8554860p9172788.bz2,但所有这些值都被编辑成这样:enwiki-latest-pages-articles-multistream-.index..>
  • 是的,这是正确的,因为我的代码是基于你的代码,我改变了我的代码来解决这个问题(如果你粘贴一个代码,我会尝试以此为基础,不要创建全新的东西)
猜你喜欢
  • 2020-03-24
  • 1970-01-01
  • 1970-01-01
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
相关资源
最近更新 更多