我尝试使用BeautifulSoup从 Craigslist 提取链接,但链接被提取了100次而不是一次

1 投票
1 回答
511 浏览
提问于 2025-04-18 16:46

我正在尝试从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

撰写回答