我尝试使用BeautifulSoup从 Craigslist 提取链接,但链接被提取了100次而不是一次
我正在尝试从craigslist上提取最新的电视节目列表链接。目前我已经能获取到我想要的信息,但不知为什么,它会把这些信息提取大约100次,然后才继续下一个链接。我不太明白为什么会这样。
import urllib2
from bs4 import BeautifulSoup
import re
import time
import csv
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
# id url
url = ('http://omaha.craigslist.org/sya/')
# this opens the url
ourUrl = opener.open(url).read()
# now we are passing the url to beautiful soup
soup = BeautifulSoup(ourUrl)
for link in soup.findAll('a', attrs={'class': re.compile("hdrlnk")}):
find = re.compile('/sys/(.*?)"')
#time.sleep(1)
timeset = time.strftime("%m-%d %H:%M") # current date and time
for linka in soup.findAll('a', attrs={'href': re.compile("^/sys/")}):
find = re.compile('/sys/(.*?)"')
searchTv = re.search(find, str(link))
Tv = searchTv.group(1)
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
url = ('http://omaha.craigslist.org/sys/' + Tv)
ourUrl = opener.open(url).read()
soup = BeautifulSoup(ourUrl)
print "http://omaha.craigslist.org/sys/" + Tv
try:
outfile = open('C:/Python27/Folder/Folder/Folder/craigstvs.txt', 'a')
outfile.write(timeset + "; " + link.text + "; " + "http://omaha.craigslist.org/sys/" + Tv + '\n')
timeset = time.strftime("%m-%d %H:%M") # current date and time
except:
print "No go--->" + str(link.text)
这是我得到的输出示例:08-10 15:19; MAC mini intel core wifi dvdrw 状态很好; http://omaha.craigslist.org/sys/4612480593.html 这正是我想要的结果,只是它把这些信息提取了100多次。然后才继续到下一个列表……我现在卡住了,搞不清楚原因。希望能得到一些帮助,提前谢谢你们!
Scrapy给@alexce:
import scrapy
import csv
from tutorial.items import DmozItem
import re
import urllib2
from scrapy.selector import HtmlXPathSelector
from scrapy.spider import BaseSpider
import html2text
class DmozSpider(scrapy.Spider):
name = "dmoz"
allowed_domains = ["http://omaha.craigslist.org"]
start_urls = [
"http://omaha.craigslist.org/sya/",
]
def parse(self, response):
for sel in response.xpath('//html'):
#title = sel.xpath('a/text()').extract()
link = sel.xpath('/html/body/article/section/div/div[2]/p/span/span[2]/a').extract()[0:4]
#at this point it doesn't repeat itself, which is good!
#desc = sel.xpath('text()').extract()
print link
1 个回答
1
这里不需要嵌套循环。还有一些其他的建议和改进:
opener.open()
的结果可以直接传给BeautifulSoup
的构造函数,不需要再用read()
。urlopener
可以定义一次,然后在循环中重复使用来跟踪链接。- 使用
find_all()
,而不是findAll()
。 - 使用
urljoin()
来拼接网址的各个部分。 - 使用
csv
模块来写入分隔的数据。 - 在处理文件时,使用
with
上下文管理器。
完整的修正版本:
import csv
import re
import time
import urllib2
from urlparse import urljoin
from bs4 import BeautifulSoup
BASE_URL = 'http://omaha.craigslist.org/sys/'
URL = 'http://omaha.craigslist.org/sya/'
FILENAME = 'C:/Python27/Folder/Folder/Folder/craigstvs.txt'
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
soup = BeautifulSoup(opener.open(URL))
with open(FILENAME, 'a') as f:
writer = csv.writer(f, delimiter=';')
for link in soup.find_all('a', class_=re.compile("hdrlnk")):
timeset = time.strftime("%m-%d %H:%M")
item_url = urljoin(BASE_URL, link['href'])
item_soup = BeautifulSoup(opener.open(item_url))
# do smth with the item_soup? or why did you need to follow this link?
writer.writerow([timeset, link.text, item_url])
这是代码生成的结果:
08-10 16:56;Dell Inspiron-15 Laptop;http://omaha.craigslist.org/sys/4612666460.html
08-10 16:56;computer????;http://omaha.craigslist.org/sys/4612637389.html
08-10 16:56;macbook 13 inch 160 gig wifi dvdrw ;http://omaha.craigslist.org/sys/4612480237.html
08-10 16:56;MAC mini intel core wifi dvdrw great cond ;http://omaha.craigslist.org/sys/4612480593.html
...
顺便提一下,由于你需要跟踪链接,获取数据并输出到 csv
文件中,Scrapy
可能会非常适合这个任务。它有 规则
、链接提取器
,并且可以 直接将爬取的项目序列化为 csv
。