首页 > 解决方案 > 将函数作为函数参数传递时的网页抓取问题

问题描述

您好,我已经创建了两个单独调用效果很好的函数。但是当我尝试对这些函数使用 for 循环时,我的参数出现了问题。

第一个函数搜索并获取链接以传递给第二个函数。

USER_AGENT = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}

def searchsport(terme):
        url = 'https://www.verif.com/recherche/{}/1/ca/d/?ville=null'.format(terme)
        response = requests.get(url, headers= USER_AGENT)
        response.raise_for_status()
        return terme, response.text
    
def crawl(keyword):    
    if __name__ == '__main__':
        try:
            keyword, html = searchsport(keyword)
            soup = bs(html,'html.parser')
            table = soup.find_all('td', attrs={'class': 'verif_col1'})

            premier = []
            for result in table:
                link = result.find('a', href=True)
                premier.append(link)
                truelink = 'https://www.verif.com/'+str(premier[0]).split('"')[1]
            #print("le lien", truelink)
        except Exception as e:
            print(e)
        finally:
            time.sleep(10)
    return truelink

抓取链接的第二个功能。

def single_text(item_url):
    source_code = requests.get(item_url)
    print('nivo1 ok')
    plain_text = source_code.text # La page en html avec toutes ces balises
    soup = bs(plain_text,features="lxml" ) 
    print('nivo2 ok')
    table = soup.find('table',{'class':"table infoGen hidden-smallDevice"}) # on cherche que la balise table
    print('nivo1 ok', '\n', table)
    table_rows = table.find_all('tr') # les données de tables sont dans les celulles tr
    #print(table_rows)

    l = []
    for tr in table_rows:
        td = tr.find_all('td')
        row = row = [tr.text.strip() for tr in td] 
        l.append(row)
        # On enleve certains caractères unitiles
        df = pd.DataFrame(l)
    return df

当我在链接上测试它们时,所有这些功能都有效。

现在我有一个 csv 文件,其中包含使用 searchsport() 在网站中搜索的公司名称,并且返回的链接被传递给 single_text() 以进行抓取。

for keyword in list(pd.read_csv('sport.csv').name):
    l = crawl(keyword)
    print(l) # THIS PRINT THE LINK
    single_item(l)    # HERE I GOT THE PROBLEME

错误:


nivo1 ok
nivo2 ok
nivo1 ok 
 None

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-55-263d95d6748c> in <module>
      3     l = crawl(keyword)
      4 
----> 5     single_item(item_url=l)

<ipython-input-53-6d3b5c1b1ee8> in single_item(item_url)
      7     table = soup.find('table',{'class':"table infoGen hidden-smallDevice"}) # on cherche que la balise table
      8     print('nivo1 ok', '\n', table)
----> 9     table_rows = table.find_all('tr') # les données de tables sont dans les celulles tr
     10     #print(table_rows)
     11 

AttributeError: 'NoneType' object has no attribute 'find_all'

当我运行它时,我得到了一个 df.

single_item(item_url="https://www.verif.com/societe/COMPANYNAME-XXXXXXXXX/").head(1)

我的预期结果应该是每个关键字都有两个 DataFrame。为什么它不起作用?

标签: pythonfor-loopweb-scrapingbeautifulsoup

解决方案


您的错误表明您尝试针对尚未填充的变量运行 find_all(),即找不到可以对其运行 find_all() 的标签。我已经通过包含对NoneType的语句测试来处理这个问题

if VALUE is not None:
    ## code when the tag is found
else:
    ## code when tag is not found 

我认为这是你需要做这样的更新的一点,

  for tr in table_rows:
    if tr is not None:
        td = tr.find_all('td')
        row = row = [tr.text.strip() for tr in td] 
        l.append(row)
        # On enleve certains caractères unitiles
        df = pd.DataFrame(l)
    else:
        ## code to run when tr isn't populated

有一个更丰富多彩的例子,其中一些 XML 正在被解析,这在这里起作用


推荐阅读