【问题标题】:I cannot crawl HTML text using BeautifulSoup我无法使用 BeautifulSoup 抓取 HTML 文本
【发布时间】:2020-03-22 10:37:07
【问题描述】:

在我上一个问题(How to speed up parsing using BeautifulSoup?)中,我问了如何更快地爬取HTML网站,答案对我帮助很大。

但是我遇到了另一个问题。这是关于爬票的价格。

我在网页中收到 JSON 文本,指的是我上一个问题的答案。我可以在 JSON 中获取几乎所有有关节日的信息,例如标题、日期、地点、海报图片 url 和表演者。

但是没有关于定价的信息,所以我尝试在网站的其他部分获取价格。

当我打开谷歌浏览器开发者模式时,有一个关于定价的表格(包括韩语,但你不必懂):

<table cellpadding="0" cellspacing="0">
    <colgroup>
        <col>
        <col style="width:20px;">
        <col>
    </colgroup>
    <tbody id="divSalesPrice">
        <tr>
            <td>2일권(입장권)</td>
            <td>&nbsp;</td>
            <td class="costTd">
                <span>140,000 원</span>
            </td>
        </tr>
        <tr>
            <td>1일권(입장권)</td>
            <td>&nbsp;</td>
            <td class="costTd">
                <span>88,000 원</span>
            </td>
        </tr>
    </tbody>
</table>

跨度标签中的数字(140000、80000)是我要提取的价格。所以我认为使用 Soup 会有效:

from bs4 import BeautifulSoup
import requests


def Soup(content):
    soup = BeautifulSoup(content, 'lxml')
    return soup


def DetailLink(url):
    req = requests.get(url)
    soup = Soup(req.content)
    spans = soup.findAll('span', class_='fw_bold')
    links = [f'{url[:27]}{span.a["href"]}' for span in spans]
    return links


def Price():
    links = DetailLink('http://ticket.interpark.com/TPGoodsList.asp?Ca=Liv&SubCa=Fes')
    with requests.Session() as request:
        for link in links:
            req = request.get(link)
            soup = Soup(req.content)
            price = soup.find('tbody', id='divSalesPrice')
            print(price)


Price()

然而,结果令人失望……

<tbody id="divSalesPrice">
<!-- 등록된 기본가 가져오기 오류-->
<tr>
<td colspan="3" id="liBasicPrice">
<ul>
</ul>
</td>
</tr>
</tbody>

评论“등록된 기본가 가져오기 오류”的意思是“获取价格时出错。”

是否意味着网站运营商阻止了其他用户在页面中抓取价格信息?

【问题讨论】:

  • 当您首先在本地保存网页并将其用作输入时,您的代码是否有效?
  • @usr2564301 没有。在保存的HTML文件中,还有一条关于错误的注释。
  • 晚安亲爱的邦邦 - 非常感谢您的回复 - 我很高兴。但是,如果我尝试在 ATOM 上的 MX-Linux 上运行它,我会得到以下信息:`文件“/home/martin/.atom/python/examples/bs_ticket_interpark.py”,第 14 行链接 = [f'{url[ :27]}{span.a["href"]}' for span in spans] ^ SyntaxError: invalid syntax [Finished in 0.507s]` - 为什么会这样 - 我现在没有胶水

标签: python beautifulsoup


【解决方案1】:

好的,如果我们仔细看,价格数据不是在请求页面时获取的,而是在之后加载的,这意味着我们需要从其他地方获取价格数据。

如果你在 chrome 中检查网络部分,会有这个奇怪的 url:

它有你要找的数据:

现在您唯一需要做的就是获取地点 ID 和产品 ID。如您所见,您可以从主页获取这些:

vPC 是位置 ID,vGC 是产品 ID,您也可以从 url 获取产品 ID。

然后这段代码解释了其余部分:

import requests, re, json

# Just a random product url, you can adapt the code into yours.
url = "http://ticket.interpark.com/Ticket/Goods/GoodsInfo.asp?GroupCode=20002746"

data = requests.get(url).text

# I used regex to get the matching values `vGC` and `vPC`
vGC = re.search(r"var vGC = \"(\d+)\"", data).groups()[0]
vPC = re.search(r"var vPC = \"(\d+)\"", data).groups()[0]

# Notice that I placed placeholders to use `format`. Placeholders are `{}`.
priceUrl = "http://ticket.interpark.com/Ticket/Goods/GoodsInfoJSON.asp?Flag=SalesPrice&GoodsCode={}&PlaceCode={}"

# Looks like that url needs a referer url and that is the goods page, we will pass it as header.
lastData = requests.get(priceUrl.format(vGC, vPC), headers={"Referer": url}).text

# As the data is a javascript object but inside it is a json object,
# we can remove the callback and parse the inside of callback as json data:
lastData = re.search(r"^Callback\((.*)\);$", lastData).groups()[0]
lastData = json.loads(lastData)["JSON"]

print(lastData)

输出:

[{'DblDiscountOrNot': 'N',
  'GoodsName': '뷰티풀 민트 라이프 2020 - 공식 티켓',
  'PointDiscountAmt': '0',
  'PriceGradeName': '입장권',
  'SalesPrice': '140000',
  'SeatGradeName': '2일권'},
 {'DblDiscountOrNot': 'N',
  'GoodsName': '뷰티풀 민트 라이프 2020 - 공식 티켓',
  'PointDiscountAmt': '0',
  'PriceGradeName': '입장권',
  'SalesPrice': '88000',
  'SeatGradeName': '1일권'}]

【讨论】:

  • 谢谢,我明白了。您的代码运行良好。但是为什么当我直接在网络浏览器中访问 url "ticket.interpark.com/Ticket/Goods/…" 时看不到 JSON 格式的内容呢?我只能看到一个空字符串。
  • 因为正如我在 cmets 中所写,标题 Referer 出于某种原因是必需的,这就是我们在这里传递产品 url 的原因。
  • 如果你问我怎么可能知道是否将Referer放在这里,我尝试直接发送与请求的页面相同的请求,然后删除不必要的参数、标题等,直到我无法获取数据。就在那一刻,当我删除标题 Referer 时,我无法获取数据。
  • 那是不是只有Referer属性值正确才可以成功打开价格数据页面?也就是说,页面开发者是否有意让用户只能通过售票页面打开价格数据页面?
  • 是与否,我再次检查了请求并仅使用 http://ticket.interpark.com/ 作为 Referer 并且它有效。看起来开发人员仅在请求来自该域时才接受请求。
猜你喜欢
  • 2020-11-10
  • 2021-10-24
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
  • 2017-08-26
相关资源
最近更新 更多