【问题标题】:scraper only returning results for first 2 inputs刮板仅返回前 2 个输入的结果
【发布时间】:2014-10-03 23:59:08
【问题描述】:

我正在尝试构建一个导入 csv 文件的抓取工具,然后将 csv 中的每一行附加到一个 url,然后为特定字段抓取该 url。到目前为止,该工具添加了数据的所有 url 和抓取,但它只返回前 2 个的数据并只显示其余的 url:

import urllib
import re
import requests
from numpy import genfromtxt
from time import sleep

my_data = genfromtxt('ASINS.csv', delimiter=',', dtype=None)

for ASIN in my_data[:20]:
    url = "http://www.amazon.com/gp/product/" + ASIN[1:11]
    sleep(1.5)
    website_html = requests.get(url).text
    print len(website_html)
    print url

    ranks = re.findall(r'#.\sin\s.*', website_html)
    for rank in ranks:
        print rank

输出只返回第一个的抓取,示例如下:

344781
http://www.amazon.com/gp/product/B00DPE9EQO
#1 in Beauty (<a href="http://www.amazon.com/gp/bestsellers/beauty">See Top 100 in     Beauty</a>)
1378
http://www.amazon.com/gp/product/B00CD0H1ZC
327515
http://www.amazon.com/gp/product/B00GP184WO
1378
http://www.amazon.com/gp/product/B00CAZAU62
1378
http://www.amazon.com/gp/product/B00KCFAZTE
1378
http://www.amazon.com/gp/product/B00C7DYBX0
3

以及来自 csv 的片段:

B00DPE9EQO  
B00CD0H1ZC  
B00GP184WO  
B00CAZAU62  
B00KCFAZTE  
B00C7DYBX0  
B00IS8Y0HK  
B00CKFL93K  
B00DDT116M  
B00GYF65TK  
B00JV8L5N8  

谁能给我任何关于它为什么会这样做的意见?

【问题讨论】:

    标签: python html web-scraping python-requests


    【解决方案1】:

    帮助我抓取您请求的数据的几件事:

    完整代码:

    from time import sleep
    
    from bs4 import BeautifulSoup
    from numpy import genfromtxt
    import requests
    
    
    my_data = genfromtxt('ASINS.csv', delimiter=',', dtype=None)
    
    # initialize a session
    session = requests.Session()
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36'}
    
    for ASIN in my_data[:20]:
        url = "http://www.amazon.com/gp/product/" + ASIN[1:11]
        sleep(1.5)
    
        response = session.get(url, headers=headers)
        soup = BeautifulSoup(response.content)
    
        print url
        # get best seller rankings
        for rank in soup.select('ul.zg_hrsr li.zg_hrsr_item'):
            print rank.text
        print "----"
    

    打印:

    http://www.amazon.com/gp/product/B00DPE9EQO
    
    #1
    in Health & Personal Care > Vitamins & Dietary Supplements > Vitamins > Vitamin C > C-Complex
    
    
    #1
    in Beauty > Skin Care > Face > Creams & Moisturizers > Fluids & Lotions > Fluids
    
    
    #1
    in Beauty > Skin Care > Face > Oils & Serums
    
    ----
    http://www.amazon.com/gp/product/B00CD0H1ZC
    
    #1
    in Pet Supplies > Dogs > Grooming > Shedding Tools
    
    
    #1
    in Pet Supplies > Cats > Grooming > Shedding Tools
    
    ----
    http://www.amazon.com/gp/product/B00GP184WO
    
    #1
    in Health & Personal Care > Health Care > Sleep & Snoring > Sleeping Masks
    
    ----
    ...
    

    【讨论】:

    • 哇这个效果很好!如果我只想返回第一个类别而不是子类别,我将如何更改该部分?
    • @amazingacademy 让我问你第一类是什么意思。例如,对于this product,您想要的输出是什么?谢谢。
    • 例如,产品将在健康和个人护理 > 维生素和膳食补充剂中排名第一,在健康和个人护理中排名第三。如果不止一个,它会在亚马逊产品页面上列出。我只想返回第一个。
    • 所以对于该产品,仅返回健康和个人护理 > 维生素和膳食补充剂 > 维生素 > 维生素 C > C-复合物排名第一
    • @amazingacademy 好吧,一种选择是将break 放在print rank.text 行之后。另一个,使用find() 而不是select()print soup.find('li', class_='zg_hrsr_item').text。希望对您有所帮助。
    【解决方案2】:

    首先,所有那些大小相同、长度为 1378 字节的结果可能是某种“404 Not Found”页面。我会尝试使用if len(website_html) == 1378: print website_html 进行一次测试运行并查看输出结果。如果事实证明您收到 404 Not Found 或其他一些错误,例如“您检索页面太快,我们认为您是机器人,所以我们不会给您该页面”,那么您将知道如何修复您的代码(例如,在后一种情况下增加 sleep() 时间)。

    其次,您的正则表达式只有在 # 后面正好有一个字符时才有效。如果某项排名第 10 位或更低(例如,排名数字更高),您的正则表达式将失败。试试#\d+ 而不是#. 看看是否有帮助。

    ...啊。当我写这篇文章时,其他人给出了更好的答案。好的。我仍然会发布这个,因为我提出的建议不会重复,它们也可能会有所帮助。

    【讨论】:

    • 使用BeautifulSoup 比正则表达式好很多。忽略我的“如何修复你的正则表达式”的建议,并使用 alecxe 的答案。
    • 感谢您的提示,我对 python 还很陌生,但我现在正在研究 BeautifulSoup 和 Scrapy
    猜你喜欢
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多