【问题标题】:How to scrape a table and its links如何抓取表格及其链接
【发布时间】:2021-02-28 07:06:27
【问题描述】:

我想要做的是采取以下网站

然后选择执行年份,输入 Last Statement Link,然后检索语句...也许我会创建 2 个字典,都以执行编号作为键。

之后,我会按长度对陈述进行分类,除了“标记”拒绝给予或没有给予。

最后,所有内容都将在 SQLite 数据库中编译,然后我会显示一个图表,显示每年有多少消息(按类型分组)。

Beautiful Soup 似乎是要走的路,我已经在打印执行年份时遇到了麻烦......当然,我最终对打印执行年份并不感兴趣,但这似乎是一个检查至少我的代码是否正确定位我想要的标签的好方法。

tags = soup('td')
for tag in tags:
    print(tag.get('href', None))

为什么前面的代码只打印None?

先谢谢了。

【问题讨论】:

  • 试试 Selenium 库,它更强大。它允许您与网页交互(即点击链接、输入值、等待元素加载等)。

标签: python-3.x web-scraping html-parsing


【解决方案1】:

使用 pandas 获取和操作表格。这些链接是静态的,我的意思是它们可以很容易地用罪犯的名字和姓氏重新创建。

然后,你可以使用requestsBeautifulSoup来抓取罪犯的最后一句话,非常感人。

方法如下:

import requests
import pandas as pd

def clean(first_and_last_name: list) -> str:
    name = "".join(first_and_last_name).replace(" ", "").lower()
    return name.replace(", Jr.", "").replace(", Sr.", "").replace("'", "")


base_url = "https://www.tdcj.texas.gov/death_row"
response = requests.get(f"{base_url}/dr_executed_offenders.html")

df = pd.read_html(response.text, flavor="bs4")
df = pd.concat(df)
df.rename(columns={'Link': "Offender Information", "Link.1": "Last Statement URL"}, inplace=True)

df["Offender Information"] = df[
    ["Last Name", 'First Name']
].apply(lambda x: f"{base_url}/dr_info/{clean(x)}.html", axis=1)

df["Last Statement URL"] = df[
    ["Last Name", 'First Name']
].apply(lambda x: f"{base_url}/dr_info/{clean(x)}last.html", axis=1)

df.to_csv("offenders.csv", index=False)

这让你:

编辑:

我实际上继续添加了获取所有罪犯最后陈述的代码。

import random
import time

import pandas as pd
import requests
from lxml import html

base_url = "https://www.tdcj.texas.gov/death_row"
response = requests.get(f"{base_url}/dr_executed_offenders.html")
statement_xpath = '//*[@id="content_right"]/p[6]/text()'


def clean(first_and_last_name: list) -> str:
    name = "".join(first_and_last_name).replace(" ", "").lower()
    return name.replace(", Jr.", "").replace(", Sr.", "").replace("'", "")


def get_last_statement(statement_url: str) -> str:
    page = requests.get(statement_url).text
    statement = html.fromstring(page).xpath(statement_xpath)
    text = next(iter(statement), "")
    return " ".join(text.split())


df = pd.read_html(response.text, flavor="bs4")
df = pd.concat(df)

df.rename(
    columns={'Link': "Offender Information", "Link.1": "Last Statement URL"},
    inplace=True,
)

df["Offender Information"] = df[
    ["Last Name", 'First Name']
].apply(lambda x: f"{base_url}/dr_info/{clean(x)}.html", axis=1)

df["Last Statement URL"] = df[
    ["Last Name", 'First Name']
].apply(lambda x: f"{base_url}/dr_info/{clean(x)}last.html", axis=1)

offender_data = list(
    zip(
        df["First Name"],
        df["Last Name"],
        df["Last Statement URL"],
    )
)

statements = []
for item in offender_data:
    *names, url = item
    print(f"Fetching statement for {' '.join(names)}...")
    statements.append(get_last_statement(statement_url=url))
    time.sleep(random.randint(1, 4))

df["Last Statement"] = statements
df.to_csv("offenders_data.csv", index=False)

这将需要几分钟,因为代码“休眠”了 14 秒之间的任何时间,或多或少,因此服务器不会被滥用。

完成此操作后,您将得到一个 .csv 文件,其中包含所有罪犯的数据及其陈述(如果有的话)。

【讨论】:

  • 如果您觉得我的回答有用,请考虑投票和/或接受它。 stackoverflow.com/help/someone-answers
  • 感谢 baduker 抽出宝贵时间给出如此详细的答案。尽管如此,我正在寻找的是使用执行编号作为 SQL DB 的键,并添加执行的年份(我猜是读取日期的最后四个字符),整个最后一条语句(即为什么我需要能够单击该链接),并为该消息添加一个值(0 表示未给出,1 表示短,2 表示长)。另外,为了安装熊猫,安装 miniconda 而不是完整的 anaconda 会有什么问题吗?
  • 我帮不了你。您必须做出与本地开发环境相关的决定。至于数据库,表格数据应该很容易按照您想要的方式解析。
  • 我明白了。再一次,我尝试安装 anaconda(默认情况下和 pandas),但我尝试运行一个非常简单的代码来在命令行中“打印”表格,但我收到了这条消息。 import pandas as pd ModuleNotFoundError: No module named 'pandas' 有什么建议吗?
  • 令人惊叹的@baduker。它创建了 csv 就好了。现在我将弄清楚如何将其转换为 sql 表,删除我不感兴趣的列,删除日期的日期和月份,并添加一个列来对语句进行分类: 之后,我只需要创建分层的年度直方图。非常感谢...顺便说一句,我找到了 html5lib 的解决方案,我卸载了所有 Python 相关程序,重新安装了最新版本,并且回溯更改为“AttributeError:模块'html5lib.treebuilders'没有属性'_base'” ,这很容易修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 2019-06-05
  • 2019-08-14
  • 1970-01-01
  • 2017-09-07
相关资源
最近更新 更多