Skip to main content
Tweeted twitter.com/StackCodeReview/status/1551583058670899209
edited tags; edited title
Link
200_success
  • 144.2k
  • 22
  • 188
  • 473

Get the 64 most popular items from a list of tree species using webscraping

Source Link

Get the 64 most popular items from a list using webscraping

I made this python program to find the 64 most common elements of a list stored in a text file. Since this works using binomial names of trees I decided to use the number of mentions in PubMed Central as a metric of popularity. I am just a beginner and somewhat self-taught so I'd like to know if there are any ways of either optimizing this code or improving readability and whether it follows webscraping best practices. The output will be used to seed Facebook polls inside a botany group. Currently the input file has 81825 rows and can be found in this GitHub repository: https://github.com/ascyphermoonshot/larch-madness

import os
import random
import requests
import bs4
import re
from progress.bar import Bar
os.chdir(r"C:\Users\HP\Desktop\larch_madness") #or whatever your filepath is
trees=open('tree_list.txt',mode='r')
trees.seek(0)
treelist=trees.read().splitlines()
treelist=[tree.replace(" ","+").lower() for tree in treelist]
trees.close()
random.shuffle(treelist)
testlist=treelist
baseurl="https://www.ncbi.nlm.nih.gov/pmc/?term=%22{}%22"
finalists=[]
class Tree:
    def __init__(self,binomial,popularity):
        self.binomial=binomial.replace("+"," ").capitalize()
        self.popularity=popularity
    def __str__(self):
        return self.binomial
def popsearch(baseurl,tree):
    searchurl=baseurl.format(tree)
    try:
        sresult=requests.get(searchurl,timeout=10)
    except:
        try:
            sresult=requests.get(searchurl,timeout=10)
        except:
            try:
                sresult=requests.get(searchurl,timeout=10)
            except:
                #print("timeout")
                return None
    soup=bs4.BeautifulSoup(sresult.text,"lxml")
    def noresults(soup):
        stext=str(soup)
        return "No items found." in stext
    if not noresults(soup):
        try:
            resfound=str(soup.find('a', {'title' : 'Total Results'}).text)
            #print(resfound)
            num=re.search(r"(?<=\()\d+(?=\))",resfound)
            num=num.group(0)
            #print(num)
            return(int(num))
        except:
            #print ("not found")
            return None
    else:
        #print("no results")
        return None
def avoid_riots(finalists):
    favs=['Sequoiadendron giganteum','Rhizophora mangle','Ginkgo biloba','Hura crepitans','Taxus baccata','Sequoia sempervivens','Pinus longaeva','Ceiba petandra','Hippomane mancinella','Dracaena cinnabari','Juniperus virginiana','Dendrocnide moroides','Artocarpus heterophyllus','Litchi chinensis','Angiopteris evecta','Pyrus calleryana']
    diff=list(set(finalists[0:-15]) - set(favs))
    if len(diff)<0:
        for x in range(len(diff)):
            try:
                finalists.pop()
            except:
                pass
    finalists.extend(favs)
    finalists=set(finalists)
    return list(finalists)
if __name__ == '__main__':
    bar = Bar('Scraping', max=len(testlist),suffix='%(percent)d%%')
    for tree in testlist:
        #print(tree.replace("+"," ").capitalize())
        popularity=popsearch(baseurl,tree)
        if popularity!=None:
            finalists.append(Tree(tree,popularity))
            #print("found")
        bar.next()
    bar.finish()
    print("\n"*3)
    finalists.sort(key=lambda x: x.popularity, reverse=True)
    print(len(finalists))
    finalists=finalists[0:64]
    tfinalists=[x.binomial for x in finalists]
    tfinalists=avoid_riots(tfinalists)
    random.shuffle(tfinalists)
    for tree in tfinalists:
        print(tree)
    with open('final tree list.txt', 'w') as f:
        f.writelines("%s\n" % l for l in tfinalists)