MENU

使用urllib依据输入次数多次检索不同网页

• March 25, 2020 • 学习

题目来源

Access Web Data的一道练习:

The program will use urllib to read the HTML from the data files below, extract the href= vaues from the anchor tags, scan for a tag that is in a particular position relative to the first name in the list, follow that link and repeat the process a number of times and report the last name you find.
Start at: http://py4e-data.dr-chuck.net/known_by_Aimie.html
Find the link at position 18 (the first name is 1). Follow that link. Repeat this process 7 times. The answer is the last name that you retrieve.
Hint: The first character of the name of the last page that you will load is: E

大意就是写一个程序来检索某一个网页中的某一处链接,然后根据输入的次数来决定重复该操作多少次。有意思的是py4e还给了这么一段骚操作:

The web pages tweak the height between the links and hide the page after a few seconds to make it difficult for you to do the assignment without writing a Python program.

通过输入来决定循环的次数

因为题目中要使程序能够根据输入来确定循环的次数,基本语法不扎实导致我立马被困住,询问某位弟弟之后才知道使用range()函数,实现代码很简单:

a =  input('输入循环次数:')
b = range(int(a))
for i in b:
    print ('hello world')

使用clear()函数清空表格

解决了循环次数的问题,我以为东风具备,风风火火的写下了第一版代码,思路主要是根据建立一个新列表,然后把读取到的链接放进去。因为列表是有顺序的,这样我就可以使程序根据我输入的链接位置来抓取列表中该序号的链接,通过循环从而实现第N次网页检索。

import urllib.request, urllib.parse, urllib.error
from bs4 import BeautifulSoup
url = input ('Enter URL:')
count = input('Enter count:')
counts = int(count)
position = input('Enter position:')
positions = int(position)
link = list()
for i in range(counts+1):
    html = urllib.request.urlopen (url)
    soup = BeautifulSoup(html,'html.parser')
    tags = soup('a')
    for tag in tags :
        link.append(tag.get('href', None))
    url = link[positions-1]
    print (url)
    continue

从结果可以看到,除了第一次运行有成功检索新网页之外,其他几次都在重复检索之前的网页。检查了代码之后发现问题出现在link这个列表,因为我每一次循环都会继续往这个列表里面加东西,也就是说之前加入的并没有消失,所以导致我检索的网页一直是一开始的那个位置。所以我引入clear()函数在每次循环后清空一遍列表。

import urllib.request, urllib.parse, urllib.error
from bs4 import BeautifulSoup
url = input ('Enter URL:')
count = input('Enter count:')
counts = int(count)
position = input('Enter position:')
positions = int(position)
link = list()
for i in range(counts+1):
    html = urllib.request.urlopen (url)
    soup = BeautifulSoup(html,'html.parser')
    tags = soup('a')
    for tag in tags :
        link.append(tag.get('href', None))
    url = link[positions-1]
    link.clear()
    print (url)
    continue

再次运行,可以看到得出正确结果了。

查找标签返回的是list!

我本来以为就这样结束了,然而因为传作业的时候有点慢我就发了邮件给助教,助教帮我传了作业后顺便瞟了一眼我的代码之后:

助教的回复

我看完恍然大悟,才想起来BeautifulSoup查找标签之后,返回的值是一个列表。所以我根本不需要像上面那样再去创建一个新的列表,而是可以直接对标签中的列表项进行索引。

import urllib.request, urllib.parse, urllib.error
from bs4 import BeautifulSoup
url = input ('Enter URL:')
count = input('Enter count:')
counts = int(count)
position = input('Enter position:')
positions = int(position)
for i in range(counts):
    html = urllib.request.urlopen (url)
    soup = BeautifulSoup(html,'html.parser')
    tags = soup('a')
    targettag = tags[positions-1]
    url = targettag.get('href', None)
    print (url)
    continue

这样子就不需要再多加一个循环就可以得出一样的效果。这个代码还是臃肿了,应该是可以有更精简的方式,下次再说吧。

总结

不得不感叹Python的在爬取网页这方面的优越性以及基本语法不扎实真的是处处受堵,另外再记一下查找特定种类标签的语句免得忘了又要重新去找。

# Retrieve all of the anchor tags
tags = soup('a')
for tag in tags:
   # Look at the parts of a tag
   print 'TAG:',tag
   print 'URL:',tag.get('href', None)
   print 'Contents:',tag.contents[0]
   print 'Attrs:',tag.attrs
Archives QR Code
QR Code for this page
Tipping QR Code