Python-使用ID提取链接
我正在学习Python——通过尝试刮取数据来获得漂亮的汤。我有一个HTML页面与此格式Python-使用ID提取链接,python,xpath,beautifulsoup,lxml,Python,Xpath,Beautifulsoup,Lxml,我正在学习Python——通过尝试刮取数据来获得漂亮的汤。我有一个HTML页面与此格式 span id listing-name-1 span class address span preferredcontact="1" a ID websiteLink1 span id listing-name-2 span class address span preferredcontact="2" a ID websiteLink2 span id listing-name-3 span clas
span id listing-name-1
span class address
span preferredcontact="1"
a ID websiteLink1
span id listing-name-2
span class address
span preferredcontact="2"
a ID websiteLink2
span id listing-name-3
span class address
span preferredcontact="3"
a ID websiteLink3
等等,多达40个这样的条目
我希望这些类/ID中的文本的顺序与HTML页面上的顺序相同
首先,我尝试了类似这样的方法来获得清单-name-1
import urllib2
from BeautifulSoup import BeautifulSoup
page = urllib2.urlopen("http://www.yellowpages.com.au/search/listings?clue=architects&locationClue=New+South+Wales&x=45&y=12")
soup = BeautifulSoup(page)
soup.find(span,attrs={"id=listing-name-1"})
它抛出一个现有连接被远程主机强制关闭的错误
我不知道如何解决这个问题。我需要两件事的帮助:
soup.find(span,attrs={“id=listing-name-1”})
谢谢大家! 第二部分的答案很简单:
import urllib2
from BeautifulSoup import BeautifulSoup
page = urllib2.urlopen("http://www.yellowpages.com.au/search/listings?clue=architects&locationClue=New+South+Wales&x=45&y=12")
soup = BeautifulSoup(page)
for num in range(1, 41):
soup.find("span", attrs={"id": "listing-name-"+str(num)})
您的第一个问题似乎与python无关。尝试打印
page.read()
,看看是否有输出。尝试用webbrowser打开页面,看看是否加载
至于第二个问题,您可以将正则表达式传递给findAll
:
import re
import urllib2
from BeautifulSoup import BeautifulSoup
page = urllib2.urlopen("http://www.yellowpages.com.au/search/listings?clue=architects&locationClue=New+South+Wales&x=45&y=12")
soup = BeautifulSoup(page)
listing_names = re.compile('listing-name-[0-9]+')
listings = soup.findAll('span', id=listing_names)
print(listings)
上面列出了我机器上的所有列表,因此您的第一个问题肯定不在代码范围内。使用
lxml.html
您可以直接使用url调用parse
,这样您就不必自己调用urllib
。另外,您不需要使用find
或findall
而需要调用xpath
,这样您就可以得到;如果尝试使用find
调用下面的同一表达式,它将返回无效谓词
错误
#!/usr/bin/env python
import lxml.html
url = "http://www.yellowpages.com.au/search/listings?clue=architects&locationClue=New+South+Wales&x=45&y=12"
tree = lxml.html.parse(url)
listings = tree.xpath("//span[contains(@id,'listing-name-')]/text()")
print listings
将输出此内容,并保留顺序:
['Cape Cod Australia Pty Ltd',
'BHI',
'Fibrent Pty Ltd Building & Engineering Assessments',
...
'Archicentre']
要回答您对我的答案的评论中的问题,您要搜索的是…
,其中包含您想要的所有信息。(姓名、地址等)。然后,您可以在符合这些条件的div元素列表上循环,并使用xpath表达式提取其余信息。请注意,在本例中,我使用了container.xpath('.//span')
,它将从当前节点(container div)进行搜索,否则,如果省略
,只使用//span
,它将从树的顶部开始搜索,您将得到匹配的所有元素的列表,选择容器节点后,这不是您想要的
#!/usr/bin/env python
import lxml.html
url = "http://www.yellowpages.com.au/search/listings?clue=architects&locationClue=New+South+Wales&x=45&y=12"
tree = lxml.html.parse(url)
container = tree.xpath("//div[@class='listingInfoContainer']")
listings = []
for c in container:
data = {}
data['name'] = c.xpath('.//span[contains(@id,"listing")]/text()')
data['address'] = c.xpath('.//span[@class="address"]/text()')
listings.append(data)
print listings
哪些产出:
[{'name': ['Cape Cod Australia Pty Ltd'],
'address': ['4th Floor 410 Church St, North Parramatta NSW 2151']},
{'name': ['BHI'],
'address': ['Suite 5, 65 Doody St, Alexandria NSW 2015']},
{'name': ['Fibrent Pty Ltd Building & Engineering Assessments'],
'address': ["Suite 3B, Level 1, 72 O'Riordan St, Alexandria NSW 2015"]},
...
{'name': ['Archicentre'],
'address': ['\n Level 3, 60 Collins St\n ',
'\n Melbourne VIC 3000\n ']}]
这是一个字典列表(同样,以您想要的方式保持顺序),其中包含键name
和address
,每个键都包含一个列表。最后的列表由text()
返回,它在原始html中保留\n
换行符,并将
之类的内容转换为新的列表元素。其原因的一个示例是列表项Archicenter,其中原始HTML表示为:
<span class="address">
Level 3, 60 Collins St
<br/>
Melbourne VIC 3000
</span>
科林斯街60号3楼
墨尔本维多利亚3000
尝试page.read()
并查看您是否能够检索页面内容我将首先将页面下载到本地计算机,然后计算解析部分,最后如果准备好了,插入远程文件读取…Lattyware,谢谢!它仍然向我抛出相同的错误:错误:[Errno 10054]远程主机强制关闭了一个现有连接`从回溯开始的回溯(最近一次调用):文件“F:\Documents and Settings\Bhavani\Desktop\YP.py”,第6行,在soup=beautifulsou(page)
@BhavaniKannan我运行了这个程序,效果很好,所以你的环境一定有问题。厕所,再次感谢!我真的不知道为什么,但当lxml解决方案运行良好时,这仍然会给我带来那个错误。也许,你能告诉我在我的环境中应该检查什么吗?我在WindowsXPSP2上使用Python2.7(空闲),我刚刚尝试在page.read()之前添加time.sleep(2)。还是不走运。老实说,我一点线索都没有——也许值得单独问一个问题。Rob,我的web浏览器(Firefox)加载的页面很好,但是page.read()会抛出一个错误。我应该做什么?提取链接的语法是什么?我试图模仿你的语法,比如Website=tree.xpath(//a[contains(@id,'websiteLink')]/href()”
,但它不起作用。另外,我刚刚发现语法Address=tree.xpath(//span[contains(@class,'Address')]/text())
只需从带有@BhavaniKannan的页面中获取所有内容,我更新了我的答案,以解决您在评论中提出的问题。我回答了我认为更重要的问题,你正试图通过你的问题来解决。有很多不同的方法来解决这个问题,但我认为这是一个好方法,简单的方法,让您选择您关心的HTML文档子集,然后从每个重复部分提取您关心的特定数据。@BhavaniKannan在选择包含地址的span时,我使用了更简单的xpath表达式//span[@class='address']
,而不是//span[contains](@class,'address')]
,因为在本例中,我知道我想精确匹配名为'address'
的类,而在另一个示例中,我试图匹配'listing-name-1','listing-name-2',等
,因此我使用了包含(@id,'listing-name-'))
函数来匹配子字符串;严格来说,我应该使用'starts with(@id,'listing name-')。除非你真的需要它,否则没有理由使用字符串函数。真不敢相信你花了这么多精力来写下它来解释事情。真是太神奇了……除非我能把它提高100000000次。非常感谢!