输入关键字 抓取所有网页( mysql+redis安装数据库安装可查阅百度(很简单))

优采云 发布时间: 2022-01-14 18:14

  输入关键字 抓取所有网页(

mysql+redis安装数据库安装可查阅百度(很简单))

  

  图像.png

  前几天因为工作需要,需要抓取一个特定的关键词来提取百度的搜索结果,将50页的数据保存到数据库或者.csv文件中。(每天爬一次)

  1.项目需要环境安装

  1)scrapy+selenium+chrome (phantomjs)

  我已经介绍了爬虫所依赖的环境的安装。大家可以参考

  2)mysql+redis安装数据库安装可以参考百度(很简单)

  2.项目开发流程介绍

  我们需要模拟用户行为,在浏览器的输入框中输入指定的关键词,模拟点击获取想要的数据,保存过滤本页显示的数据,模拟翻页抓取本页前50个关键词关键词。页面展示,获取我们想要的数据,存入.csv文件或者redis数据库,供以后数据分析。

  3.开发代码详情

  1)创建一个scrapy项目

  scrapy startproject keyword_scrawl

  scrapy genspider 重新测试

  代码中每个文件的介绍

  settings.py 是一个通用的配置文件:

  BOT_NAME : 项目名称

  蜘蛛模块:

  NEWSPIDER_MODULE:

  以下模块的配置路径

  pipelines.py 这是一个与数据存储相关的文件

  可以自定义middlewares.py,让scrapy更可控

  items.py 这个文件有点类似于django中的一个form,定义了数据保存的格式

  ,但是比django的表单应用更简单,因为它的字段非常单一。

  Spider 文件夹:此文件夹存储特定的 网站 爬虫。通过命令行,我们可以创建自己的蜘蛛。

  4.蜘蛛代码详解

  def make_requests_from_url(self, url):

if self.params['st_status'] == 1:

return Request(url, meta={'keyword': self.keyword, 'engine':self.sousu, 'phantomjs':True})

else:

return Request(url)

  首先修改spider中的make_requests_from_url函数,增加判断。当st_status==1时,我们在返回请求对象的时候添加一个meta,并在meta中携带我们要搜索的key和需要访问的浏览器地址。以及启动 phantomjs 的说明。

  接下来在我们刚刚修改的make_requests_from_url方法中,修改middlewares中间件中的类方法process_request,默认携带request和spider对象。我们可以在这里处理之前的make_requests_from_url函数返回的Request请求,然后加载selenium和phantomjs来获取我们需要访问的浏览器和关键字。这段代码会模拟用户的行为来获取关键字内容,然后返回页面的内容。在 scrapy.http 中给出 HtmlResponse 对象。这样,我们就可以在蜘蛛的parse函数中得到刚刚抓取到的内容response.body。

   # 判断页面的返回状态

if int(response.status) >= 200 and int(response.status) < 400:

if not self.params['redis_key']:

a_list = response.xpath('//h3/a/@href').extract()

for url in a_list:

if url.startswith('http://') != True and url.startswith('https://') !=True:

url = response.urljoin(url)

yield scrapy.Request(url=url, meta={'url':response.url}, callback=self.pang_bo, dont_filter=True)

if response.meta.has_key('page') != True and self.sousu == 2:

flag = 1

for next_url in response.xpath('//div[@id="page"]/a/@href').extract():

if next_url.startswith('http://') != True and next_url.startswith('https://') !=True:

nextUrl = self.start_urls[0] + next_url

regex = 'pn=(\d+)'

page_number = re.compile(regex).search(nextUrl).group(1)

if page_number and flag:

flag = 0

# 抓取前50页

for page in range(10,500,10):

next_page = 'pn=' + str(page)

old_page = re.compile(regex).search(nextUrl).group()

nextUrl = nextUrl.replace(old_page, next_page)

yield scrapy.Request(url=nextUrl, meta={'page':page}, callback=self.parse)

  上面的代码是获取刚才网页上显示的每一个搜索结果,并获取页面规则,模拟翻50页,将50页的所有内容提交给self.pang_bo函数处理。在这里做了一个页面去重复!

   # 处理item

def parse_text(self, response):

item = {}

try:

father_url = response.meta["url"]

except:

father_url = "''"

try:

item['title'] = response.xpath('//title/text()').extract_first().replace('\r\n','').replace('\n','').encode('utf-8')

except:

item['title'] = "''"

item['url'] = response.url

item['domain'] = ''

item['crawl_time'] = time.strftime('%Y%m%d%H%M%S')

item['keyword'] = ''

item['Type_result'] = ''

item['type'] = 'html'

item['filename'] = 'yq_' + str(int(time.time())) + '_0' + str(rand5())+'.txt'

item['referver'] = father_url

item['like'] = ''

item['transpond'] = ''

item['comment'] = ''

item['publish_time'] = ''

return item

def pang_bo(self, response):

# 过略掉百度网页

if 'baidu.com' not in response.url and 'ctrip.com' not in response.url and 'baike.com' not in response.url:

item = self.parse_text(response)

content = soup_text(response.body)

if len(content) > 3000:

content = content[:3000]

#elif len(content) == 0:

#yield scrapy.Request(url=response.url, meta={'url':response.url, 'phantomjs':True}, callback=self.pang_bo)

body = item['url']+','+item['crawl_time']+','+item['title'].replace(',','') +','+content+'\n'

if '正在进入' == item['title']:

file_name = os.path.join(self.filetxt,time.strftime('%Y%m%d%H')+'keyword.csv')

with open(file_name, 'a') as b:

b.write(body)

else:

filename = os.path.join(self.filetxt,time.strftime('%Y%m%d%H')+'.csv')

with open(filename, 'a') as f:

f.write(body)

# 过滤网页源代码

def soup_text(body):

try:

soup = BeautifulSoup(body, 'lxml')

line = re.compile(r'\s+')

line = line.sub(r'', soup.body.getText())

p2 = re.compile(u'[^\u4e00-\u9fa5]') # 中GDAC\u4e00\u9fa5

str2 = p2.sub(r'', line)

outStr = str2.strip(',')

except:

outStr = ''

return outStr

  这段代码主要是跳过了一些不必要的网站,然后提取item字段,以及页面正文(这里过滤源代码),然后将获取到的内容保存到.csv文件中。这只是一个简单的爬虫。对于反爬虫,设置如下:

  LOG_STDOUT = True # 将进程所有的标准输出(及错误)将会被重定向到log中(为了方便调试)

DOWNLOAD_DELAY=0.25 # 下载延时设置 单位秒

DOWNLOAD_TIMEOUT = 60 # 下载超时设置(单位秒)

CONCURRENT_ITEMS = 200 # 同时处理的itmes数量

CONCURRENT_REQUESTS = 16 # 同时并发的请求

  今天的代码已经介绍到这里了,但我还是想说:“做一个爱分享的程序员,有什么问题请留言。” 如果你觉得我的文章还可以,欢迎关注点赞。谢谢!

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线