Python 如何改进这种网络爬虫逻辑?

Python 如何改进这种网络爬虫逻辑?,python,web-scraping,beautifulsoup,Python,Web Scraping,Beautifulsoup,我在一个网络爬虫上工作,它将使用请求和bs4只抓取内部链接 我有一个粗略的工作版本下面,但我不知道如何正确处理检查,如果一个链接已经爬网之前或没有 import re import time import requests import argparse from bs4 import BeautifulSoup internal_links = set() def crawler(new_link): html = requests.get(new_link).text

我在一个网络爬虫上工作,它将使用请求和bs4只抓取内部链接

我有一个粗略的工作版本下面,但我不知道如何正确处理检查,如果一个链接已经爬网之前或没有

import re
import time
import requests
import argparse
from bs4 import BeautifulSoup


internal_links = set()

def crawler(new_link):


    html = requests.get(new_link).text 
    soup = BeautifulSoup(html, "html.parser")
    for link in soup.find_all('a', attrs={'href': re.compile("^http://")}):
        if "href" in link.attrs:
            print(link)
            if link.attrs["href"] not in internal_links:
                new_link = link.attrs["href"]
                print(new_link)
                internal_links.add(new_link)
                print("All links found so far, ", internal_links)
                time.sleep(6)
                crawler(new_link)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('url', help='Pass the website url you wish to crawl')
    args = parser.parse_args()

    url = args.url

    #Check full url has been passed otherwise requests will throw error later

    try:
        crawler(url)

    except:
        if url[0:4] != 'http':
            print('Please try again and pass the full url eg http://example.com')



if __name__ == '__main__':
    main()
以下是输出的最后几行:

All links found so far,  {'http://quotes.toscrape.com/tableful', 'http://quotes.toscrape.com', 'http://quotes.toscrape.com/js', 'http://quotes.toscrape.com/scroll', 'http://quotes.toscrape.com/login', 'http://books.toscrape.com', 'http://quotes.toscrape.com/'}
<a href="http://quotes.toscrape.com/search.aspx">ViewState</a>
http://quotes.toscrape.com/search.aspx
All links found so far,  {'http://quotes.toscrape.com/tableful', 'http://quotes.toscrape.com', 'http://quotes.toscrape.com/js', 'http://quotes.toscrape.com/search.aspx', 'http://quotes.toscrape.com/scroll', 'http://quotes.toscrape.com/login', 'http://books.toscrape.com', 'http://quotes.toscrape.com/'}
<a href="http://quotes.toscrape.com/random">Random</a>
http://quotes.toscrape.com/random
All links found so far,  {'http://quotes.toscrape.com/tableful', 'http://quotes.toscrape.com', 'http://quotes.toscrape.com/js', 'http://quotes.toscrape.com/search.aspx', 'http://quotes.toscrape.com/scroll', 'http://quotes.toscrape.com/random', 'http://quotes.toscrape.com/login', 'http://books.toscrape.com', 'http://quotes.toscrape.com/'}
因为它只会找到以http开头的链接,而且很多内部页面上的链接都没有,但是当我这样尝试的时候

for link in soup.find_all('a')
程序运行非常短暂,然后结束:

http://books.toscrape.com
{'href': 'http://books.toscrape.com'}
http://books.toscrape.com
All links found so far,  {'http://books.toscrape.com'}
index.html
{'href': 'index.html'}
index.html
All links found so far,  {'index.html', 'http://books.toscrape.com'}
你可以减少

for link in soup.find_all('a', attrs={'href': re.compile("^http://")}):
        if "href" in link.attrs:
            print(link)
            if link.attrs["href"] not in internal_links:
                new_link = link.attrs["href"]
                print(new_link)
                internal_links.add(new_link)


这使用了一个grabs,它只使用http协议限定标记元素,并使用集合理解来确保没有重复。然后,它会使用任何新链接更新现有集。我对python了解不够,无法评论使用.update的效率,但我相信它会修改现有的集合,而不是创建一个新的集合。此处列出了更多组合集合的方法:

谢谢,这部分是可行的,但它仍然存在一个问题:如果没有http eg,它无法找到链接,因此它只是在顶级页面上爬行,而没有深入。相关路径总是以/author开头吗?你能提供一个示例url吗?您只需使用css或syntax soup将相对href URL的选择器添加到现有选择器中。选择(“a[href^='http:'],a[href^='http:'],a[href^='/'])不确定是否需要转义我测试的最后一个/with//,但该站点没有为内部链接使用完整路径,这就是为什么它找不到所有链接的原因。我尝试了一个有完整url路径的网站,现在它可以工作了,理想情况下这两种情况都可以,但现在就可以了,谢谢。我将很快发布我完成的代码并标记答案。你可以添加相对路径开始,但你需要使用css或语法,并避开前导/,考虑它可能实际上需要\/而不是//。如果你愿意,我可以用这个链接来更新。
for link in soup.find_all('a', attrs={'href': re.compile("^http://")}):
        if "href" in link.attrs:
            print(link)
            if link.attrs["href"] not in internal_links:
                new_link = link.attrs["href"]
                print(new_link)
                internal_links.add(new_link)
links = {link['href'] for link in soup.select("a[href^='http:']")}
internal_links.update(links)