繁体   English   中英

使用BS4进行爬取,但在解析时将HTML弄乱了

[英]Scraping with BS4 but HTML gets messed up when parsed

我在使用BeautifulSoup4和Python3抓取网站时遇到了麻烦。 我使用dryscrape来获取HTML,因为它需要启用JavaScript才能显示(但据我所知,页面本身从未使用过)。

这是我的代码:

from bs4 import BeautifulSoup
import dryscrape

productUrl = "https://www.mercadona.es/detall_producte.php?id=32009"
session = dryscrape.Session()
session.visit(productUrl)
response = session.body()
soup = BeautifulSoup(response, "lxml")
container1 = soup.find("div","contenido").find("dl").find_all("dt")
container3 = soup.find("div","contenido").find_all("td")

现在,我想读取container3内容,但是:

type(container3)

返回:

bs4.element.ResultSet

type(container1)相同,但长度为0!

所以我想在寻找<td>标记之前先知道如何进入container3 ,所以我将其写入了文件。

container3 = soup.find("div","contenido")
soup_file.write(container3.prettify())

并且,这是该文件的链接: https : //pastebin.com/xc22fefJ

在我要刮擦的桌子前,一切都弄糟了。 我不明白为什么,从Firefox看URL源代码看起来一切正常。

这是更新的解决方案:

url = 'https://www.mercadona.es/detall_producte.php?id=32009'

rh = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.9',
    'Connection': 'keep-alive',
    'Host': 'www.mercadona.es',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}

s = requests.session()
r = s.get(url, headers = rh)

对此的响应使您Please enable JavaScript to view the page content. 信息。 但是,它也包含浏览器使用javascript发送的必要的hidden数据,这些数据可以从开发人员工具的“网络”标签中看到。

TS015fc057_id: 3
TS015fc057_cr: a57705c08e49ba7d51954bea1cc9bfce:jlnk:l8MH0eul:1700810263
TS015fc057_76: 0
TS015fc057_86: 0
TS015fc057_md: 1
TS015fc057_rf: 0
TS015fc057_ct: 0
TS015fc057_pd: 0

其中,第二个(长字符串)由javascript生成。 我们可以使用js2py类的库来运行代码,该库将返回要在请求中传递的所需字符串。

soup = BeautifulSoup(r.content, 'lxml')
script = soup.find_all('script')[1].text

js_code = re.search(r'.*(function challenge.*crc;).*', script, re.DOTALL).groups()[0] + '} challenge();'
js_code = js_code.replace('document.forms[0].elements[1].value=', 'return ')

hidden_inputs = soup.find_all('input')
hidden_inputs[1]['value'] = js2py.eval_js(js_code)

fd = {i['name']: i['value'] for i in hidden_inputs}

rh = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Referer': 'https://www.mercadona.es/detall_producte.php?id=32009',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.9',
    'Connection': 'keep-alive',
    'Content-Length': '188',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Cache-Control': 'max-age=0',
    'Host': 'www.mercadona.es',
    'Origin': 'https://www.mercadona.es',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}

# NOTE: the next one is a POST request, as opposed to the GET request sent before
r = s.post(url, headers = rh, data = fd)
soup = BeautifulSoup(r.content, 'lxml')

结果如下:

>>> len(soup.find('div', 'contenido').find_all('td'))
70
>>> len(soup.find('div', 'contenido').find('dl').find_all('dt'))
8

编辑

显然,javascript代码仅需要运行一次。 结果数据可用于多个请求,如下所示:

for i in range(32007, 32011):
    r = s.post(url[:-5] + str(i), headers = rh, data = fd)
    soup = BeautifulSoup(r.content, 'lxml')
    print(soup.find_all('dd')[1].text)

结果:

Manzana y plátano 120 g
Manzana y plátano 720g (6x120) g
Fresa Plátano 120 g
Fresa Plátano 720g (6x120g)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM