python-3.x 如何从网站上抓取表格,而BS4选择不会找到它?

velaa5lx  于 2023-01-10  发布在  Python
关注(0)|答案(2)|浏览(113)

我正在使用下面的代码刮表元素从网址(www.sfda.gov.sa/en/cosmetics-list)。但它来空

from bs4 import BeautifulSoup
import requests
import pandas as pd
url="https://www.sfda.gov.sa/en/cosmetics-list"
res = requests.get(url)
soup = BeautifulSoup(res.content, 'html.parser')
table = soup.find('table', attrs={'class':'table table-striped display'})
table_rows = table.find_all('tr')

res = []
for tr in table_rows:
    td = tr.find_all('td')
    row = [tr.text.strip() for tr in td if tr.text.strip()]
    if row:
        res.append(row)

df = pd.DataFrame(res, columns=["ProductName", "Category", "Country", "Company"])
print(df)

运行上述代码但未获取数据

sqxo8psd

sqxo8psd1#

数据是通过XHR加载的,因此您应该使用它来获取您的信息:

url = 'https://www.sfda.gov.sa/GetCosmetics.php?page=1'
pd.DataFrame(requests.get(url).json()['results'])
示例

循环range()中的页数并收集所有数据。

import requests
import pandas as pd

data = []

for i in range(1,5):
    url = f'https://www.sfda.gov.sa/GetCosmetics.php?page={i}'
    data.extend(requests.get(url).json()['results'])

pd.DataFrame(data)
输出

| | 身份证|化妆品ID|产品通知ID|产品编号|地位|产品参数名称|产品名称|品牌名称|阿拉伯语|猫英语|县|县|制造商类型| Package 体积|单位Ar|单位|条码|制造商别名|制造商英文名称|列出的名称Ar|列名En|图像URL|批号|制造国_英语|制造国_阿拉伯语|产品创建日期|产品失效日期|子类别1|子类别AR|储存环境|保护说明|使用说明|注解|主要商业记录编号|制造许可证编号|
| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------|
| 无|小行星549105|小行星58472|小行星10518|二○二○年一月十九日一月二九一日二四五九四五|活跃|ليتسيا كوبيبا|山苍子油|摩沙生活方式|منتجات العناية بالبشرة|护肤品|الهند|印度|外国|二百五十|ملي لتر|毫升(ml)|无|موكشا لايف ستايل برودكت| Moksha生活方式产品|人字车|肖尤尔稀土贸易公司|||印度|الهند|2020年9月28日上午9时40分46秒|2025年10月5日上午9时40分46秒|香水|العطور|室温|印度语|الاستعمال الخارجي||小行星7016|法国专利555666|
| ...||||||||||||||||||||||||||||||||||||
| 九|小行星84386|小行星58481|小行星4031| 2016年1月20日-048982|活跃|جودي ثيرابي سيستيم للشعر بالبروتين| Judy蛋白质&蚕丝护发系统|朱蒂|منتجات العناية بالشعر وفروة الرأس|头发和头皮产品|印度|美国|外国|一千|ملي لتر|毫升(ml)|小行星641243925950|马马马马马马马马马马马马马马马马马|天然化妆品实验室美国公司,|شركه بيت جودي الدوليه للتجارة|拜特高迪贸易公司|||美国|印度|2016年12月25日14时40分44秒|2027年1月1日14时40分44秒|头发造型产品|人户|||||小行星7007289163|法国专利555666|

nukf8bse

nukf8bse2#

您可以使用concurrent.futures并发地抓取页面,当所有页面都完成时,将结果连接到单个 Dataframe 中:

import concurrent.futures
import json
import os

import pandas as pd
import requests

class Scrape:
    def __init__(self):
        self.root_url = "https://www.sfda.gov.sa/GetCosmetics.php?"
        self.pages = self.get_page_count()
        self.processors = os.cpu_count()

    def get_page_count(self) -> int:
        return self.get_data(url=self.root_url).get("pageCount")

    @staticmethod
    def get_data(url: str) -> dict:
        with requests.Session() as request:
            response = request.get(url, timeout=30)
        if response.status_code != 200:
            print(response.raise_for_status())

        return json.loads(response.text)

    def process_pages(self) -> pd.DataFrame:
        page_range = list(range(1, self.pages + 1))

        with concurrent.futures.ProcessPoolExecutor(max_workers=self.processors) as executor:
            return pd.concat(executor.map(self.parse_data, page_range)).reset_index(drop=True)

    def parse_data(self, page: int) -> pd.DataFrame:
        url = f"{self.root_url}page={page}"
        data = self.get_data(url=url)

        return (pd
                .json_normalize(data=data, record_path="results")
                )[["productEnName", "catEnglish", "counrtyEn", "brandName"]].rename(
            columns={"productEnName": "ProductName", "catEnglish": "Category",
                     "counrtyEn": "Country", "brandName": "Company"}
        )

if __name__ == "__main__":
    final_df = Scrape().process_pages()
    print(final_df)

相关问题