Я не могу сканировать HTML текст используя BeautifulSoup - PullRequest
1 голос
/ 22 марта 2020

В моем предыдущем вопросе ( Как ускорить разбор с помощью BeautifulSoup? ) я спросил, как быстрее сканировать HTML веб-сайт, и ответ мне очень помог.

Но я столкнулся с другой проблемой. Речь идет о сканировании цены билетов.

Я получил JSON текст на веб-странице со ссылкой на ответ на мой предыдущий вопрос. Я мог получить почти любую информацию о фестивалях в JSON, например, название, дату, местоположение, URL изображения плаката и исполнителей.

Но информации о ценах не было, поэтому я попытался узнать цену в другой части веб-сайта.

Когда я включил режим разработчика Google Chrome, есть таблица с ценами (она включает корейский язык, но вам не нужно это понимать):

<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>

Числа в теге span (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>

Комментарий '등록 된 기본가 가져 오기 오류' означает 'Ошибка произошло при получении цены. '

Означает ли это, что оператор веб-сайта заблокировал другим пользователям доступ к информации о цене на странице?

1 Ответ

2 голосов
/ 22 марта 2020

Хорошо, если мы посмотрим внимательно, данные о ценах не получаются, когда вы запрашиваете страницу, они загружаются впоследствии, это означает, что нам нужно получить данные о ценах откуда-то еще.

Если вы проверяете сеть раздел в chrome, есть этот странный URL:

enter image description here

И он содержит данные, которые вы ищете:

enter image description here

Теперь единственное, что вам нужно сделать, это получить идентификатор места и идентификатор продукта. Вы можете получить их с домашней страницы, как видите:

enter image description here

vPC - это идентификатор местоположения, а vGC - это идентификатор продукта, вы также можно получить идентификатор продукта из URL.

Тогда этот код объясняет остальное:

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일권'}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...