爬取页面上的外链

代码原型来自于《Web Scraping with Python 2ndEdition》P37页的一个案例代码。

代码的功能是根据初始的页面地址抓取该页面中的所有外链接并随机选取一个继续追踪这个外链接指向的新页面,并搜集新页面中的所有外链接随机选取一个后继续追踪。

书中实现该功能的代码整体思路是

  1. 根据给定的链接抓取该链接指向页面中所有的a标签href属性值,并将href值为外链的提取出来组成列表。外链接的标准是以www或http开头并且不包括从给定的链接中提取出来的netloc信息。
  2. 页面爬取结束后,如果外链列表中有内容则从中随机选取一个出来,以递归的方式重复步骤1。
  3. 如果页面爬取结束后,外链列表为空(也就是当前页面一个外链都没有),则重新搜集页面中所有的a标签href属性值,并将href值为内链的提取出来组成列表。内链的标准是以/或者非/的任意内容开头,但链接中包含从给定链接中提取出来的scheme://netloc。
  4. 页面爬取结束后,从内链列表中随机选取一个内链接出来,以递归的方式重复步骤1。

书中的代码对内链的定义不太准确,一般的内链应该是以/或者..开头,在生成链接的时候可以用scheme://netloc拼接内链后再交由urlopen去访问。如果内链以/开头,则拼接方式就是接单的字符串相加;如果内链以..开头,则拼接的方式可以采用替换。

prefix = f'{urlparse(url).scheme}://{urlparse(url).netloc}'
if link.attrs['href'].startswith('/'):
        links.append(prefix+link.attrs['href'] )
 else:
        links.append(link.attrs['href'].replace('..',prefix) )

修改后的全部代码如下:

from random import randint
import random
from datetime import datetime
from urllib.request import urlopen
from bs4 import BeautifulSoup
from urllib.parse import urlparse
import re

random.seed(datetime.now())

def get_internal_links(bs,url):
    prefix = f'{urlparse(url).scheme}://{urlparse(url).netloc}'
    links = []
    for link in bs.find_all('a',href=re.compile('^(/|\.\.)')):
        if link.attrs['href'] is not None and link.attrs['href'] not in links:
            if link.attrs['href'].startswith('/'):
                links.append(prefix+link.attrs['href'] )
            else:
                links.append(link.attrs['href'].replace('..',prefix) )
    return links

def get_external_links(bs,url):
    links = []
    for link in bs.find_all('a',href=re.compile('^(https|http|www)((?!'+url+').)*$')):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in links:
                links.append(link.attrs['href'])
    return links

def get_random_link(url):
    html = urlopen(url)
    bs = BeautifulSoup(html,'html.parser')
    domain = urlparse(url).netloc
    links = get_external_links(bs,domain)
    if len(links)==0:
        print(f'没有外链,将寻找新的链接...')
        address = f'{urlparse(url).scheme}://{urlparse(url).netloc}'
        print('get_random_link address: ',address)

        links = get_internal_links(bs,address)
        result = links[randint(0,len(links)-1)]
        print(f'从{result}中选取一个新的外链进行访问')
        return get_random_link(result)
    else:
        result = links[randint(0,len(links)-1)]
        print(f'选中的外链是{result}')
        return result

def  follow_link(url):
    link = get_random_link(url)
    follow_link(link)

follow_link('http://shouji.tenaa.com.cn/Mobile/MobileDetail.aspx?code=XSRnDagtFCv8xvg82UmspMQMGLV61AwQ')

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值