使用 BeautifulSoup 4 和 Requests_HTML 抓取 Javascript 网站

10V*_*0VA 6 javascript python beautifulsoup web-scraping python-requests-html

在让我的抓取工具在另一个网站上正常工作后,我正在学习如何为另一个网站 Reverb.com 构建另一个抓取工具。然而,从混响中提取信息更具挑战性,并且使用我的旧刮刀的模型的工作方式并不相同。我做了一些研究,发现使用requests_html代替requests似乎是大多数人在 Javascript 中使用的选项,就像 Reverb.com 那样。

我本质上是试图抓取标题和价格信息的文本版本,然后对不同页面进行分页或循环访问 URL 列表以获取所有内容。我有点在那里,但遇到了障碍。下面是我正在摆弄的代码的两个版本。

下面的第一个版本打印出所有看起来只有 3 页内容的内容,但它打印出所有带有标记的乐器名称和价格。然而,在 CSV 中,所有这些项目仅一起打印在 3 行上,而不是每行 1 个项目/价格对。

from requests_html import HTMLSession
from bs4 import BeautifulSoup
import csv
from fake_useragent import UserAgent


session = HTMLSession()
r = session.get("https://reverb.com/marketplace/bass-guitars?year_min=1900&year_max=2022")
r.html.render(sleep=5)
soup = BeautifulSoup(r.html.raw_html, "html.parser")

#content scrape
b = soup.findAll("h4", class_="grid-card__title") #title
for i in b:
    print(i)


p = soup.findAll("div", class_="grid-card__price") #price
for i in p:
    print(i)
Run Code Online (Sandbox Code Playgroud)

相反,此版本仅将 3 行打印到 CSV,但名称和价格被删除了所有标记。但只有当我将 更改findAll为 just时才会发生这种情况find。我读到这for html in r.html是一种无需创建 URL 列表即可循环浏览页面的方法。

from requests_html import HTMLSession
from bs4 import BeautifulSoup
import csv
from fake_useragent import UserAgent


#make csv file
csv_file = open("rvscrape.csv", "w", newline='') #added the newline thing on 5.17.20 to try to stop blank lines from writing
csv_writer = csv.writer(csv_file)
csv_writer.writerow(["bass_name","bass_price"])

session = HTMLSession()
r = session.get("https://reverb.com/marketplace/bass-guitars?year_min=1900&year_max=2022")
r.html.render(sleep=5)
soup = BeautifulSoup(r.html.raw_html, "html.parser")

for html in r.html:
    #content scrape
    bass_name = []
    b = soup.find("h4", class_="grid-card__title").text.strip() #title
    #for i in b:
    #    bass_name.append(i)
    #    for i in bass_name:
    #        print(i)

    price = []
    p = soup.find("div", class_="grid-card__price").text.strip() #price
    #for i in p:
    #    print(i)

    csv_writer.writerow([b, p])
Run Code Online (Sandbox Code Playgroud)

小智 0

为了提取搜索结果的所有页面,您需要提取下一页的链接,并继续提取,直到没有下一页可用。我们可以使用while 循环并检查下一个锚标记是否存在来做到这一点。以下脚本执行循环并将结果添加到 csv。它还打印页面的 url,以便我们估计程序所在的页面。

from requests_html import HTMLSession
from bs4 import BeautifulSoup
import csv
from fake_useragent import UserAgent


# make csv file
# added the newline thing on 5.17.20 to try to stop blank lines from writing
csv_file = open("rvscrape.csv", "w", newline='')
csv_writer = csv.writer(csv_file)
csv_writer.writerow(["bass_name", "bass_price"])

session = HTMLSession()
r = session.get(
    "https://reverb.com/marketplace/bass-guitars?year_min=1900&year_max=2022")
r.html.render(sleep=5)

stop = False
next_url = ""
while not stop:
    print(next_url)
    soup = BeautifulSoup(r.html.raw_html, "html.parser")

    titles = soup.findAll("h4", class_="grid-card__title")  # titles
    prices = soup.findAll("div", class_="grid-card__price")  # prices

    for i in range(len(titles)):
        title = titles[i].text.strip()
        price = prices[i].text.strip()
        csv_writer.writerow([title, price])

    next_link = soup.find("li", class_="pagination__page--next")
    if not next_link:
        stop = True
    else:
        next_url = next_link.find("a").get("href")
        r = session.get("https://reverb.com/marketplace" + next_url)
        r.html.render(sleep=5)
Run Code Online (Sandbox Code Playgroud)

对于目标 JavaScript 网站来说,此类数据输出架构问题非常常见。这也可以使用动态刮刀来解决。