无法处理网页中一些复杂的布局内容

Posted

技术标签:

【中文标题】无法处理网页中一些复杂的布局内容【英文标题】:Can't deal with some complicated laid-out content from a webpage 【发布时间】:2019-01-13 07:12:19 【问题描述】:

我用 Python 结合 BeautifulSoup 编写了一个脚本来解析网页中的一些内容。在登录页面中有两个表格。我需要使用第一个表中的Results 选项卡,这将导致目标页面。

从目标页面我只关注此信息Grade: M 300 metres 等等。在其上方有多个选项卡,例如1,2,3,4 等,它们具有不同的Grade 状态。我想把它们都拿回来。

由于登陆页面中的Results 选项卡没有任何链接,我不得不使用post 请求从目标页面获取内容。在这种情况下,浏览器模拟器不适合我。

底线是我需要使用六个post 请求才能到达六个Results 选项卡的内容。

我在下面粘贴的脚本可以处理最后一个results 选项卡的内容。如何修复循环以同时从所有 Results 选项卡获取内容?

这是我的尝试:

import requests
from bs4 import BeautifulSoup

url = "https://www.thedogs.com.au/Racing/Results.aspx?SearchDate=3-Jun-2018"

def get_info(session,link):
    session.headers['User-Agent'] = "Mozilla/5.0"
    res = session.get(link)
    soup = BeautifulSoup(res.text,"lxml")

    formdata = 

    for items in soup.select("#aspnetForm input"):
        if "ctl00$ContentPlaceHolder1$rptrLatestRacingResults$ctl" in items.get("name"):continue
        if "ctl00$ContentPlaceHolder1$rptrSearchResults$ctl0" in items.get("name"):
            formdata[items.get("name")] = items.get("value")
        else:
            formdata[items.get("name")] = items.get("value")

    session.headers['User-Agent'] = "Mozilla/5.0"
    req = session.post(link,data = formdata)
    soup = BeautifulSoup(req.text,"lxml")
    for iteminfo in soup.select("[id^='ctl00_ContentPlaceHolder1_tabContainerRaces_tabRace'] span"):
        if "Grade:" in iteminfo.text:
            print(iteminfo.text)

if __name__ == '__main__':
    with requests.Session() as session:
        get_info(session,url)

查看下面的两张图片(一张接一张)以识别我要获取的内容:

【问题讨论】:

你在这里的经历让我很感兴趣。看到 cmets 已被删除,我的兴趣被进一步激发。我已经打开了一个关于 meta 的问题来讨论这个问题:meta.***.com/questions/372078/… 【参考方案1】:

您可以利用 CSS 选择器 span[id$=lblResultsRaceName],它会查找所有 id 以 lblResultsRaceName 和 'td > span' 结尾的 span,它会查找所有具有直接父级 <td> 的 span:

此代码 sn-p 将检查所有比赛结果并打印所有比赛:

import requests
from bs4 import BeautifulSoup

url = "https://www.thedogs.com.au/Racing/Results.aspx?SearchDate=3-Jun-2018"

def get_info(session,link):
    session.headers['User-Agent'] = "Mozilla/5.0"
    res = session.get(link)
    soup = BeautifulSoup(res.text,"lxml")
    formdata = i['name']: i['value'] for i in soup.select('input[type=hidden]')
    for race_name, i in  zip(soup.select('span[id$=lblResultsRaceName]'), soup.select('input[id$=btnViewResults]')):
        print(race_name.text.strip())
        formdata[i['name']] = 'Results'
        req = session.post(link,data = formdata)
        soup = BeautifulSoup(req.text,"lxml")
        for panel in soup.select('div[id^=ctl00_ContentPlaceHolder1_tabContainerRaces_tabRace]'):
            print(panel.select('td > span')[0].text.strip(), panel.select('td > span')[1].text.strip())
        print('#' * 80)

if __name__ == '__main__':
    with requests.Session() as session:
        get_info(session,url)

打印:

Healsville
Race 1 Grade:  M   300 metres
Race 2 Grade:  M   350 metres
Race 3 Grade:  6/7   350 metres
Race 4 Grade:  R/W   300 metres
Race 5 Grade:  5   350 metres
Race 6 Grade:  SE   350 metres
Race 7 Grade:  4/5   350 metres
Race 8 Grade:  SE   350 metres
Race 9 Grade:  7   300 metres
Race 10 Grade:  6/7   300 metres
Race 11 Grade:  4/5   300 metres
Race 12 Grade:  5   300 metres
################################################################################
Sale
Race 1 Grade:  M   440 metres
Race 2 Grade:  M   440 metres
Race 3 Grade:  R/W   520 metres
Race 4 Grade:  7   440 metres
Race 5 Grade:  R/W   440 metres
Race 6 Grade:  4/5   520 metres
Race 7 Grade:  R/W   440 metres
Race 8 Grade:  4/5   440 metres
Race 9 Grade:  6/7   440 metres
Race 10 Grade:  R/W   440 metres
Race 11 Grade:  R/W   440 metres
Race 12 Grade:  5   520 metres
################################################################################
...and so on.

【讨论】:

它完美地做到了@Andrej。提供了一个加号。过段时间会接受的。顺便说一句,您能否简要介绍一下formdata[i['name']] = 'Results' 这一行实际上在这里做什么?谢谢。 @asmitu 使用formdata[i['name']] = 'Results' 我选择要查看的比赛结果。我通过Firefox中的源代码查看了它,这是type="submit"表单输入变量。 抱歉 Andrej 再次打扰您。 formdata[i['name']] = 'Results' 对我来说似乎有点高级,我无法解开这个谜题。当它在for loop 之前使用时,它在字典中收集了一些namesvalues。但是,当您尝试使用formdata[i['name']] = 'Results' 时,它不会只抓住单词Results 将其先前存储在字典中的内容踢出。再次感谢您提供任何见解。 @asmitu 我知道,旧的“结果”将保留在 formdata 中,但服务器将只处理添加的最后一个 - 这是此特定服务器的工作方式。

以上是关于无法处理网页中一些复杂的布局内容的主要内容,如果未能解决你的问题,请参考以下文章

将网页内容转化为PDF的三种方法

今日所学

如何显示网页的加载过程

用一篇文章,带你了解12种常见的网页布局设计

jQuery EasyUI 布局 - 为网页创建边框布局

html5里面新增的用于网页布局的标签都有哪些