数据采集与融合技术第四次大作业

作业①

1.实验内容

  • 要求:熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;Scrapy+Xpath+MySQL数据库存储技术路线爬取当当网站图书数据
  • 候选网站:http://search.dangdang.com/?key=python&act=input
  • 关键词:学生可自由选择
  • 输出信息:MySQL的输出信息如下。

  • 运行结果截图:(运行结果较多只截取部分信息)

控制台截图:


数据库截图:

2.心得体会

(1)本题是对利用scrapy对当当网进行数据爬取代码的复现,以爬取关键词为哈利波特为例。
(2)Scrapy框架思路:

(3)访问网页并进行元素审查,尤其是翻页部分

可以发现下一页的网址在li[class=”next”]的子节点a属性herf中

(4)items:定义数据结构供Spider、pipelines调用,在items.py文件中设置各类参数。

class DdscrapyItem(scrapy.Item):
    # define the fields for your item here like:
    id = scrapy.Field() #序号
    title = scrapy.Field() #标题
    author = scrapy.Field() #作者
    publisher = scrapy.Field() #出版社
    date = scrapy.Field() #时间
    price = scrapy.Field() #价格
    detail = scrapy.Field() #详细信息
    pass

(5)pipelines调用items中的信息,将封装好的信息解析出来存储到本地,所以在pipelines.py文件中进行数据库存储。

  • 编写open_spider()函数进行连接数据库
  • 编写close_spider()函数进行关闭数据库
  • 编写process_item()函数将爬取过程打印并将数据写入数据库中

(6)在spider文件夹下新建myspider.py文件并在start_requests函数中编写首次访问请求,在parse函数中获取所需数据,并注意翻页的相关信息爬取。

def start_requests(self): #首次爬取
    yield scrapy.Request(url=MySpider.url,callback=self.parse)

def parse(self, response): #获取数据
    try:
        dammit = UnicodeDammit(response.body, ["utf-8", "gbk"])
        data = dammit.unicode_markup
        selector = scrapy.Selector(text=data)
        lis = selector.xpath("//li['@ddt-pit'][starts-with(@class,'line')]")
        for li in lis:
            MySpider.count +=1
            title = li.xpath("./a[position()=1]/@title").extract_first()
            price =li.xpath("./p[@class='price']/span[@class='search_now_price']/text()").extract_first()
            author = li.xpath("./p[@class='search_book_author']/span[position()=1]/a/@title").extract_first()
            date = li.xpath("./p[@class='search_book_author']/span[position()=last()- 1]/text()").extract_first()
            publisher = li.xpath("./p[@class='search_book_author']/span[position()=last()]/a/@title ").extract_first()
            detail = li.xpath("./p[@class='detail']/text()").extract_first()
            item = DdscrapyItem()
            item["id"] = MySpider.count
            item["title"] = title.strip() if title else "None"
            item["author"] = author.strip() if author else "None"
            item["date"] = date.strip()[1:] if date else "None"
            item["publisher"] = publisher.strip() if publisher else "None"
            item["price"] = price.strip() if price else "None"
            item["detail"] = detail.strip() if detail else "None"
            #如果没有提取到信息则返回无
            yield item #返回获取对象
        if MySpider.page <= 2: #爬取3页,在原来已经爬取第一页的基础上进行判断
            MySpider.page += 1
            new_page_url = self.url % MySpider.page
            yield scrapy.Request(url=new_page_url, callback=self.parse)
    except Exception as err:
        print(err)

(7)在setting.py文件中设置打开pipeline的相关信息

ITEM_PIPELINES = {
    'ddscrapy.pipelines.DdscrapyPipeline': 300,
}

(8)编写run.py文件进行运行

from scrapy import cmdline
cmdline.execute("scrapy crawl HarryPotter -s LOG_ENABLED=False".split())

(9)遇到的问题及解决
在爬取过程中通过控制台打印的信息发现数据库总共只存储了162条信息,而一共爬取了180条信息。

查看控制台输出的信息发现detail中超出varchar的最大长度

于是在数据库中将表中bDetail类型修改为longtext

重新运行发现成功存储180条信息

作业②

1.实验内容

  • 要求:熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;使用scrapy框架+Xpath+MySQL数据库存储技术路线爬取外汇网站数据。
  • 候选网站:招商银行网:http://fx.cmbchina.com/hq/
  • 输出信息:MySQL数据库存储和输出格式
Id Currency TSP CSP TBP CBP Time
1 港币 86.60 86.60 86.26 85.65 15:36:30
2......
  • 运行结果截图:

控制台截图:

数据库截图:

2.心得体会

(1)Scrapy框架思路:

(2)访问网页并进行元素审查

可以本题的数据较小,而且每条数据的标签及其属性都很相似,因而爬取过程中需要注意爬取的是哪一个数据。

(3)items:定义数据结构供Spider、pipelines调用,在items.py文件中设置各类参数。

class FcurrencyItem(scrapy.Item):
    # define the fields for your item here like:
    id = scrapy.Field()
    currency = scrapy.Field()
    TSP = scrapy.Field()
    CSP = scrapy.Field()
    TBP = scrapy.Field()
    CBP = scrapy.Field()
    time = scrapy.Field()
    pass

(4)pipelines调用items中的信息,将封装好的信息解析出来存储到本地,所以在pipelines.py文件中进行数据库存储。

  • 初始化数据库,利用setting中所写的本地数据库信息进行数据库的连接
def __init__(self):
    self.connect = pymysql.connect(
        host=settings.MYSQL_HOST,
        db=settings.MYSQL_DBNAME,
        user=settings.MYSQL_USER,
        passwd=settings.MYSQL_PASSWD,
        charset='utf8',
        use_unicode=True) #连接数据库
    self.cursor = self.connect.cursor();
  • 打印爬取信息并将爬取数据存入数据库中
def process_item(self, item, spider):
    try:
        print("{:^5}\t{:^5}\t{:^5}\t{:^5}\t{:^5}".format(item["id"],item["TSP"],item["CSP"],item["TBP"],item["CBP"],item["time"]))
    except Exception as err:
        print(err)
    try:
        self.cursor.execute(
            """insert into fcurrency(Id, Currency, TSP, CSP, TBP, CBP , T)
            value (%s, %s, %s, %s, %s, %s, %s)""",
            (item['id'],
             item['currency'],
             item['TSP'],
             item['CSP'],
             item['TBP'],
             item['CBP'],
             item['time']))
        # 提交sql语句
        self.connect.commit()
    except Exception as error:
    # 出现错误时打印错误日志
        print(error)
    return item

(7)在spider文件夹下新建myspider.py文件并在start_requests函数中编写首次访问请求,在parse函数中获取所需数据,并注意翻页的相关信息爬取。

def start_requests(self): #访问网页
    url = 'http://fx.cmbchina.com/hq/'
    yield scrapy.Request(url=url, callback=self.parse)

def parse(self, response): #获取数据
    try:
        dammit = UnicodeDammit(response.body, ["utf-8", "gbk"])
        data = dammit.unicode_markup#解码
        selector = scrapy.Selector(text=data)
        currencys = selector.xpath("//table[@class='data']//tr")
        for currency in currencys[1:]:
            MySpider.count+=1
            Currency = currency.xpath("./td[@class='fontbold']/text()").extract_first()
            TSP = currency.xpath("./td[@class='numberright']/text()").extract_first()
            CSP = currency.xpath("./td[@class='numberright']/text()")[1].extract()
            TBP = currency.xpath("./td[@class='numberright']/text()")[2].extract()
            CBP = currency.xpath("./td[@class='numberright']/text()")[3].extract()
            Time = currency.xpath("./td[@align='center']/text()")[2].extract()
            item = FcurrencyItem()
            item["id"] = MySpider.count
            #获取信息中的文本内容
            item["currency"] = Currency.strip()
            item["TSP"] = TSP.strip()
            item["CSP"] = CSP.strip()
            item["TBP"] = TBP.strip()
            item["CBP"] = CBP.strip()
            item["time"] = Time.strip()
            yield item
        print(currencys)
    except Exception as err:
        print(err)

(6)在setting.py文件中设置网络代理和与数据库连接相关的变量

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'ex4'
MYSQL_USER = 'root'
MYSQL_PASSWD = '123456'
ITEM_PIPELINES = {
    'fcurrency.pipelines.FcurrencyPipeline': 300,
}

(8)编写run.py文件进行运行

from scrapy import cmdline
print("{:^5}\t{:^5}\t{:^5}\t{:^5}\t{:^5}".format("Id","Currency","TSP","CSP","TBP","CBP","Time"))
cmdline.execute(['scrapy','crawl','fcurrency','--nolog'])

作业③

1.实验内容

  • 要求:熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容;使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、“深证A股”3个板块的股票数据信息。
  • 候选网站:东方财富网:http://quote.eastmoney.com/center/gridlist.html#hs_a_board
  • 输出信息:MySQL数据库存储和输出格式如下,表头应是英文命名例如:序号id,股票代码:bStockNo……,由同学们自行定义设计表头:
序号 股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
1 688093 N世华 28.47 62.22% 10.92 26.13万 7.6亿 22.34 32.0 28.08 30.2 17.55
2......
  • 运行结果部分截图:

控制台截图:

数据库截图:

2.心得体会

(1)本次需要爬取3个板块的数据,所以要查看3个板块网址直接的规律

可以发现各版块的网址在html#后不同,其他均相同,可以设置一个start_url和字符进行一个连接同时利用多线程对3个网页进行爬取加快速度

start_url = "http://quote.eastmoney.com/center/gridlist.html#%s"
shares = ["hs_a_board", "sh_a_board", "sz_a_board"]
for share in shares:
    url = start_url % share
    T = threading.Thread(target=Spider(url)) #设置多线程
    T.setDaemon(False)
    T.start()
    time.sleep(random.randint(1,3))

(2)对于翻页,检查下一页的元素,然后利用click()动作进行翻页

nextpage=driver.find_element_by_xpath("//div[@id='main-table_paginate']/a[2]")
nextpage.click()

(3)建立Chrome浏览器的访问请求

chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options=chrome_options)

(4)对每页数据利用xpath语句进行获取,其中每页第一行数据(list[0])为标题,所以从第二行(list[1])开始获取数据。

for li in list[1:]:
    no = li.find_element_by_xpath(("./td[1]")).text
    code = li.find_element_by_xpath(("./td[2]")).text
    name = li.find_element_by_xpath(("./td[3]")).text
    newprice = li.find_element_by_xpath(("./td[5]")).text
    up = li.find_element_by_xpath(("./td[6]")).text
    down = li.find_element_by_xpath(("./td[7]")).text
    num = li.find_element_by_xpath(("./td[8]")).text
    count = li.find_element_by_xpath(("./td[9]")).text
    swing = li.find_element_by_xpath(("./td[10]")).text
    high = li.find_element_by_xpath(("./td[11]")).text
    low = li.find_element_by_xpath(("./td[12]")).text
    today = li.find_element_by_xpath(("./td[13]")).text
    yes = li.find_element_by_xpath(("./td[14]")).text

(5)建立与数据库的连接,并将爬取的数据存储到数据库中

db = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="123456", db="ex4", charset="utf8") #连接本地数据库
cursor = db.cursor()
try:
    cursor.execute("""insert into shares(no,code,name,newprice,up,down,num,count,swing,high,low,today,yes) value (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
              ,(no, code, name, newprice, up, down, num, count, swing, high, low, today,yes)) #将数据插入数据库中
    db.commit() #提交
except Exception as err:
    print(err)

(6)遇到的问题及解决
在进行翻页的时候出现报错:

检查之后发现在翻页时忘记设置休眠时间,使得翻页速度跟不上爬取速度,因而在翻页时要设置一定的翻页时间

posted @ 2021-11-12 16:03  imperceptibly  阅读(24)  评论(0编辑  收藏  举报