George、卟壞 2025-03-04 19:22 采纳率: 16.7%
浏览 8

为什么销量和库存爬取不上信息?求解,急!

img

img

img

img

img


为啥销量和库存爬取不上信息?


import time
import random
import requests
from lxml import etree
import csv
from concurrent.futures import ThreadPoolExecutor

def header_x():
    user_agents = [
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:3.0) Gecko/20100101 Firefox/34.0',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.5.2',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
    ]
    headers = {"User-Agent": random.choice(user_agents)}
    return headers

def fetch_books(session, category_id, page):
    books = []
    base_url = "https://www.bookuu.com/"
    url = f"https://www.bookuu.com/search.php?cid={category_id}&page={page}"
    headers = header_x()
    response = session.get(url, headers=headers)  # 将 timeout 参数添加到 requests.get()
    if response.status_code != 200:
        print(f"Failed to fetch page {page} for category {category_id}, status code: {response.status_code}")
        return books

    html = etree.HTML(response.text)
    lis = html.xpath("//div[contains(@class, 'wd-640')]")  # 提取包含书籍信息的 HTML 元素

    for li in lis:
        try:
            # 提取书名
            name = li.xpath(".//a/text()")[0].strip()
            # 提取作者
            author_div = li.xpath(".//div[contains(@class, 'wd-30p')]/span[2]/text()")
            author = author_div[0].strip() if author_div else "未知"

            # 提取价格
            price = li.xpath(".//div[@class='lh-30']/span/text()")[0].strip()

            # 提取出版社
            publisher_info = li.xpath(".//div[contains(@class , 'wd-30p')]/span[contains(@style,'color: #212121;')]/text()")
            publisher = publisher_info[0].strip() if publisher_info else "未知"

            # 提取出版日期
            pub_date_info = li.xpath(".//div[contains(@class , 'wd-30p')]/span[contains(@style,'color: #212121;')]/text()")
            pub_date = pub_date_info[0].strip() if pub_date_info else "未知"

            son_path = li.xpath("./a/@href")[0]  # 提取子链接
            son_url = base_url + son_path  # 构造完整的子页面 URL
            resp_son = session.get(son_url, headers=header_x(), timeout=10)  # 请求子页面
            html_son = etree.HTML(resp_son.text)  # 解析子页面 HTML

            # 提取销量
            sales = li.xpath(".//span[@class='cl-3']/text()")
            sales = sales[0].strip() if sales else "0"

            # 提取库存
            stock_info = html_son.xpath(".//span[@id='www_goods_stores']/text()")
            stock = stock_info[0].split("库存:")[1].strip() if stock_info else "无"

            books.append([name, author, price, publisher, pub_date, sales, stock])  # 将书籍信息添加到列表
        except (IndexError, Exception) as e:
            print(f"提取书籍信息失败: {e}")
            continue

    return books  # 返回当前页的书籍信息

def save_to_csv(books, filename):
    with open(filename, mode='w', encoding='utf-8', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(['书名', '作者', '价格', '出版社', '出版日期', '销量', '库存'])
        writer.writerows(books)

def main():
    category_ids = ['1018', ]  # 示例分类 ID
    pages = 5  # 每个分类爬取的页数

    session = requests.Session()
    session.cookies.set("cookie", "parent_qimo_sid_92464560-3f16-11e9-8a25-8d8585556f17=842fa102-a4ef-4247-b504-7856a955c2d4; accessId=92464560-3f16-11e9-8a25-8d8585556f17; pv_id=ce979e0a977dca375ff535c9c9e9176c; _uab_collina=174098147261023766843709; wwwsid=d32f327bda1b54a31c8b6d0feb1bb4fd; tfstk=gAVoQ6AzN8kSJWr92ol5B8tvGsWxNUGIYkdKvXnF3moX23d88vq30u9JeyS7xWm400E8eye08uaUxv_SvDo3vyyRk1CTPzGITXjO61FcLspTx4kr4r7E5VTPkYWIMVaZTGIOMdncuOlU2-1DQs4qc2ArY0rEgjun0BuUY0k20V0tTDrUYxRq540eaLuygKoj8XoUYX70ubKCU0NUgSS49ps5pJq_i4DobrX6wQOszhnUzqOeT00oEZ4rmBRUi-p4YToPCEnIw0arrk16Nbk3L7h4ai5E_RZ0tAlGpaMz--qIwS7eUcy82vFSn3JrSbmoQ7kAsZljL-Vmw7SBCrUm4AcYHts-pbquCcMPhiZ3o0EUZx-lDDeTk7k0bid0Av2UwjPP01jyBKJNnmdIuwF2dpMrlqm9V2RfrJVFnm7cod7IUqgSXZbDdpMrlqmOoZvNOYujPcC..; PHPSESSID=4ingct6o5llmvvsbn9ssakcl83; href=https%3A%2F%2Fwww.bookuu.com%2Findex.php; qimo_seosource_0=%E7%AB%99%E5%86%85; qimo_seokeywords_0=; qimo_seosource_92464560-3f16-11e9-8a25-8d8585556f17=%E7%AB%99%E5%86%85; qimo_seokeywords_92464560-3f16-11e9-8a25-8d8585556f17=; qimo_xstKeywords_92464560-3f16-11e9-8a25-8d8585556f17=; pageViewNum=238")  # 替换为实际的 Cookie

    all_books = []

    # 使用多线程爬取每个分类的每一页
    with ThreadPoolExecutor(max_workers=5) as executor:
        futures = []
        for cid in category_ids:
            for page in range(1, pages + 1):
                futures.append(executor.submit(fetch_books, session, cid, page))

        for future in futures:
            all_books.extend(future.result())

    save_to_csv(all_books, "books.csv")

if __name__ == "__main__":
    main()


    # '101802', '1020', '1021', '1022', '1023', '103713', '103714', '103715', '103716', '103701',
    # '103702', '103703', '103704', '103705', '103706', '103707', '103708', '103708', '103711', '103701',
    # '1038', '1039', '1040', '1042', '1043', '1044', '1045', '1024', '1025', '1026', '1041',
    # '1026', '1027', '1028', '1029', '1030', '1032', '1033', '1034', '1035', '1017', '1048', '1048',
    # '1049', '1050', '1051', '1052', '1053', '1054', '1055', '1056', '1057', '1058', '1011',
  • 写回答

4条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-03-12 09:23
    关注
    让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供,如果还有疑问可以点击头像关注私信或评论。
    如果答案让您满意,请采纳、关注,非常感谢!

    从你提供的代码和问题描述来看,销量和库存信息无法爬取的原因可能有以下几种:

    1. XPath 表达式错误

    • 你在代码中使用了 li.xpath(".//span[@class='cl-3']/text()") 来提取销量信息,但根据你提供的图片(虽然无法直接查看图片),这个 XPath 表达式可能不正确。你需要检查页面的 HTML 结构,确保 XPath 表达式能够正确匹配到销量信息。
    • 同样,库存信息的 XPath 表达式 html_son.xpath(".//span[@id='www_goods_stores']/text()") 也可能有问题。你需要确认页面中库存信息的具体位置和标签。

    2. 页面结构变化

    • 网站可能会动态加载某些内容(如销量和库存信息),这些内容可能通过 JavaScript 动态生成,而不是直接包含在初始的 HTML 响应中。这种情况下,使用 requests 库无法获取到这些动态加载的内容。
    • 你可以使用浏览器开发者工具(如 Chrome 的 DevTools)查看页面加载的网络请求,看看是否有额外的 AJAX 请求来获取销量和库存信息。如果有,你需要模拟这些请求来获取数据。

    3. 反爬虫机制

    • 网站可能使用了反爬虫机制,阻止你获取某些敏感信息(如销量和库存)。你可以尝试增加请求头中的 User-AgentReferer 等信息,或者使用代理 IP 来规避反爬虫机制。

    4. 子页面请求失败

    • 你在代码中请求了子页面来获取库存信息,但子页面请求可能失败。你可以检查 resp_son.status_code 来确认子页面请求是否成功。如果请求失败,可能是由于网络问题、反爬虫机制或 URL 构造错误。

    5. 数据格式问题

    • 销量和库存信息可能以不同的格式存在(如 JSON、XML 等),而不是直接嵌入在 HTML 中。你需要检查页面源代码,看看是否有隐藏的 JSON 数据或其他格式的数据。

    解决方案建议:

    1. 检查 XPath 表达式

      • 使用浏览器开发者工具检查页面结构,确保 XPath 表达式正确匹配到销量和库存信息。
    2. 处理动态加载内容

      • 如果销量和库存信息是通过 JavaScript 动态加载的,你可以使用 SeleniumPyppeteer 等工具来模拟浏览器行为,获取动态加载的内容。
    3. 模拟 AJAX 请求

      • 如果销量和库存信息是通过 AJAX 请求获取的,你可以使用 requests 库模拟这些请求,获取数据。
    4. 增加请求头信息

      • 增加更多的请求头信息,如 RefererAcceptAccept-Language 等,以规避反爬虫机制。
    5. 调试子页面请求

      • 检查子页面请求的 URL 和响应状态码,确保子页面请求成功。

    示例代码改进:

    def fetch_books(session, category_id, page):
        books = []
        base_url = "https://www.bookuu.com/"
        url = f"https://www.bookuu.com/search.php?cid={category_id}&page={page}"
        headers = header_x()
        response = session.get(url, headers=headers)
        if response.status_code != 200:
            print(f"Failed to fetch page {page} for category {category_id}, status code: {response.status_code}")
            return books
    
        html = etree.HTML(response.text)
        lis = html.xpath("//div[contains(@class, 'wd-640')]")
    
        for li in lis:
            try:
                # 提取书名
                name = li.xpath(".//a/text()")[0].strip()
                # 提取作者
                author_div = li.xpath(".//div[contains(@class, 'wd-30p')]/span[2]/text()")
                author = author_div[0].strip() if author_div else "未知"
    
                # 提取价格
                price = li.xpath(".//div[@class='lh-30']/span/text()")[0].strip()
    
                # 提取出版社
                publisher_info = li.xpath(".//div[contains(@class , 'wd-30p')]/span[contains(@style,'color: #212121;')]/text()")
                publisher = publisher_info[0].strip() if publisher_info else "未知"
    
                # 提取出版日期
                pub_date_info = li.xpath(".//div[contains(@class , 'wd-30p')]/span[contains(@style,'color: #212121;')]/text()")
                pub_date = pub_date_info[0].strip() if pub_date_info else "未知"
    
                son_path = li.xpath("./a/@href")[0]
                son_url = base_url + son_path
                resp_son = session.get(son_url, headers=header_x(), timeout=10)
                if resp_son.status_code != 200:
                    print(f"Failed to fetch subpage: {son_url}, status code: {resp_son.status_code}")
                    continue
    
                html_son = etree.HTML(resp_son.text)
    
                # 提取销量
                sales = li.xpath(".//span[@class='cl-3']/text()")
                sales = sales[0].strip() if sales else "0"
    
                # 提取库存
                stock_info = html_son.xpath(".//span[@id='www_goods_stores']/text()")
                stock = stock_info[0].split("库存:")[1].strip() if stock_info else "无"
    
                books.append([name, author, price, publisher, pub_date, sales, stock])
            except (IndexError, Exception) as e:
                print(f"提取书籍信息失败: {e}")
                continue
    
        return books
    

    总结:

    你需要仔细检查页面结构和 XPath 表达式,确保它们能够正确匹配到销量和库存信息。如果信息是通过 JavaScript 动态加载的,你可能需要使用 SeleniumPyppeteer 来获取这些数据。同时,确保你的请求头信息和 Cookie 设置正确,以规避反爬虫机制。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月4日