首页 > 解决方案 > BeautifulSoup 在解析链接时返回空列表

问题描述

我是网络抓取的新手,我正在尝试使用 BeautifulSoup 从网站中提取链接和表格数据。但是,即使网页中有链接,它也不会返回任何内容。我可以通过在浏览器中检查网页来找到链接。

这是我正在使用的代码

from bs4 import BeautifulSoup as soup
from selenium import webdriver

driver = webdriver.Chrome()
url = "http://www.ms2soft.com/tcds/?loc=Txdot&mod=tcds&local_id=57CC441"
driver.get(url)

content = driver.page_source.encode('utf-8').strip()
pageData = soup(content, "html.parser")
links = pageData.find_all('a')

该网页给出了达拉斯市的交通数据。我也使用过requestsurllib模块,但没有运气。

标签: pythonbeautifulsouphtml-parsing

解决方案


不幸的是,这个特定的服务不会向 API 发出任何直接请求 - 这将非常方便,因为这意味着您可以简单地模仿对同一 API 的请求并(很可能)返回易于解析的 JSON。

这个页面碰巧使用 ajax 并提供 .asp 文件——这意味着服务器执行一些脚本来生成实际的 HTML,然后它会为您提供服务。它也恰好为每个不同的表提供不同的 .asp 文件 - 基本上我是说这不是那么有趣。您可能必须为每个不同的表编写略有不同的解决方案才能获得所需的内容。

这是我想出的一个基础项目。您创建一个requests.Session来跟踪 cookie(在这种情况下,服务器碰巧关心会话 cookie)。然后,您对要抓取的每个表的 .asp 资源发出实际请求(在我的示例中,我只是抓取 AADT(年平均每日流量)表) - 每个表都有一个唯一的 URL,您可以通过查看浏览器的网络/资源/流量记录器。查看 Google Chrome 开发者工具中的 Query-String / Requests 参数,我选择了一些参数,它们似乎对您要抓取的特定记录很重要。然后我想出了一个粗略的列表理解,以使抓取的数据更具表现力——这可能是每个表都不同的部分。

def main():

    import requests
    from bs4 import BeautifulSoup
    from itertools import groupby

    session_url = "https://txdot.ms2soft.com/tcds/tsearch.asp"

    session = requests.Session()
    session_response = session.get(session_url)
    session_response.raise_for_status()

    aadt_url = "https://txdot.ms2soft.com/tcds/ajax/tcds_tdetail_aadt.asp"

    params = {
        "offset": "0",
        "agency_id": "97",
        "local_id": "57CC441"
    }

    aadt_response = session.get(aadt_url, params=params)
    aadt_response.raise_for_status()

    soup = BeautifulSoup(aadt_response.content, "html.parser")

    rows = list(list(group) for key, group in groupby([item.find(text=True, recursive=False) for item in soup.find_all("td", {"class": "FormRow"})], key=lambda i: i and i.isprintable()) if key)
    print(rows)

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

输出:

[['2018', '1,482'], ['2017', '1,482', '246', '17'], ['2016', '1,488', '255', '17', '100'], ['2015', '1,199', '155', '13']]
>>> 

推荐阅读