簡體   English   中英

BeautifulSoup 從中提取數據<script> with unicode

[英]BeautifulSoup extract data from <script> with unicode

我正在嘗試在 html 頁面的腳本中解析 JSON。

import requests
from bs4 import BeautifulSoup
import json

headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36 OPR/64.0.3417.47",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "fr-FR,en;q=0.5",
    "Accept-Encoding": "gzip, deflate",
    "Connection": "keep-alive",
    "Cache-Control": "max-age=0",
    "Upgrade-Insecure-Requests": "1",
}

proxy = "http://stack:overflow@45.135.149.142:14758"

url = "https://www.seloger.com/list.htm?projects=2%2C5&types=2%2C1&natures=1%2C2%2C4&places=%5B%7Bci%3A60088%7D%5D&enterprise=0&qsVersion=1.0"
r = requests.get(url, proxies={"http": proxy, "https": proxy}, headers=headers)
soup = BeautifulSoup(r.text, 'html.parser')
for script in soup.find_all('script'):
    if "initialData" in script.text:
        data = script.text.split('JSON.parse("', 1)[1].split('");window["tags"]', 1)[0]
        json_data = json.loads(data)

並返回此錯誤:

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

問題是 " 沒有轉換為引號 " ,這會觸發 json 解碼器錯誤。

此外,每當我打印腳本代碼時,都會打印 " 而不是 "。在將其傳遞給 json.loads 之前,我已經嘗試以多種格式進行編碼和解碼,但沒有任何效果。

只有在直接從請求響應中解析代碼時才會出現問題。 我無法復制這個問題。 此代碼按預期工作:

snippet = '''<script>
window["initialData"] = JSON.parse("{\u0022foo\u0022:\u0022bar\u0022,\u0022xxx\u0022:\u0022xyz\u0022}")
</script>
'''
soup = BeautifulSoup(snippet, 'html.parser')
for script in soup.find_all('script'):
    data = script.text.split('JSON.parse("')[1].split('")')[0]
    json_data = json.loads(data)
    print(json_data)
    # output : {'foo': 'bar', 'xxx': 'xyz'}

我怎樣才能解決這個問題?

您可以使用正則表達式(不是最好的方法)來做到這一點,但這對我有用:

import requests,json,re
proxy='http://stack:overflow@45.135.149.142:14758'
url='https://www.seloger.com/list.htm?projects=2%2C5&types=2%2C1&natures=1%2C2%2C4&places=%5B%7Bci%3A60088%7D%5D&enterprise=0&qsVersion=1.0'
r = requests.get(url, proxies={"http": proxy, "https": proxy})
json_data = json.loads(json.loads('"' + re.search(r'JSON\.parse\("(.+)"\);w', r.text).group(1) + '"')) # note it needs to be double wrapped
json_data.keys()
# dict_keys(['cards', 'navigation', 'SEO', 'tracking', 'adverts', 'bookmarks', 'failure', 'engine'])

您嘗試抓取的內容包括 unicode 轉義序列,這些序列似乎實際上已被轉義。

我發現的解決方案涉及編碼然后解碼字符串,盡管可能有更好的方法:

data.encode("utf-8").decode("unicode-escape")

我還對您的代碼進行了一些其他調整,特別是在解析數據的方式方面,在我用作演示/測試的這個片段中可以看到:

json_re = re.compile(r"window\[\"initialData\"] = JSON\.parse\(\"(.*)\"\);window\[\"tags\"]")

with open("../out/temp.html", 'rb') as file_in:
    soup = BeautifulSoup(file_in.read(), 'lxml')

raw_data = ""
for script in soup.find_all('script'):
    if "initialData" in script.text:
        res_text = script.get_text(strip=True)
        raw_data = json_re.search(res_text).group(1)
        break

print(raw_data)
t_1 = raw_data.encode("utf-8")
print(t_1)

t_2 = t_1.decode("unicode-escape")
print(t_2)

t_3 = json.loads(t_2)
print(t_3)

也許問題是拆分步驟,但我在 json 和編碼方面遇到了類似的問題。 嘗試使用“utf-8”或“latin”重新編碼 response.text。 有時它對我有用。 希望能幫助到你!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM